package com.datamate.gateway.security;

import lombok.Getter;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * 权限规则匹配器
 */
@Component
public class PermissionRuleMatcher {
    private static final Set<HttpMethod> READ_METHODS = Set.of(HttpMethod.GET, HttpMethod.HEAD);
    private static final Set<HttpMethod> WRITE_METHODS = Set.of(HttpMethod.POST, HttpMethod.PUT, HttpMethod.PATCH, HttpMethod.DELETE);

    private final AntPathMatcher pathMatcher = new AntPathMatcher();
    private final List<String> whiteListPatterns = List.of(
            "/api/auth/login",
            "/api/auth/login/**"
    );
    private final List<PermissionRule> rules = buildRules();

    public boolean isWhitelisted(String path) {
        return whiteListPatterns.stream().anyMatch(pattern -> pathMatcher.match(pattern, path));
    }

    public String resolveRequiredPermission(HttpMethod method, String path) {
        for (PermissionRule rule : rules) {
            if (rule.matches(method, path, pathMatcher)) {
                return rule.getPermissionCode();
            }
        }
        return null;
    }

    private List<PermissionRule> buildRules() {
        List<PermissionRule> permissionRules = new ArrayList<>();
        addModuleRules(permissionRules, "/api/data-management/**", "module:data-management:read", "module:data-management:write");
        addModuleRules(permissionRules, "/api/annotation/**", "module:data-annotation:read", "module:data-annotation:write");
        addModuleRules(permissionRules, "/api/data-collection/**", "module:data-collection:read", "module:data-collection:write");
        addModuleRules(permissionRules, "/api/evaluation/**", "module:data-evaluation:read", "module:data-evaluation:write");
        addModuleRules(permissionRules, "/api/synthesis/**", "module:data-synthesis:read", "module:data-synthesis:write");
        addModuleRules(permissionRules, "/api/knowledge-base/**", "module:knowledge-base:read", "module:knowledge-base:write");
        addModuleRules(permissionRules, "/api/operator-market/**", "module:operator-market:read", "module:operator-market:write");
        addModuleRules(permissionRules, "/api/orchestration/**", "module:orchestration:read", "module:orchestration:write");
        addModuleRules(permissionRules, "/api/content-generation/**", "module:content-generation:use", "module:content-generation:use");

        permissionRules.add(new PermissionRule(READ_METHODS, "/api/auth/users/**", "system:user:manage"));
        permissionRules.add(new PermissionRule(WRITE_METHODS, "/api/auth/users/**", "system:user:manage"));
        permissionRules.add(new PermissionRule(READ_METHODS, "/api/auth/roles/**", "system:role:manage"));
        permissionRules.add(new PermissionRule(WRITE_METHODS, "/api/auth/roles/**", "system:role:manage"));
        permissionRules.add(new PermissionRule(READ_METHODS, "/api/auth/permissions/**", "system:permission:manage"));
        permissionRules.add(new PermissionRule(WRITE_METHODS, "/api/auth/permissions/**", "system:permission:manage"));
        return permissionRules;
    }

    private void addModuleRules(List<PermissionRule> rules,
                                String pathPattern,
                                String readPermissionCode,
                                String writePermissionCode) {
        rules.add(new PermissionRule(READ_METHODS, pathPattern, readPermissionCode));
        rules.add(new PermissionRule(WRITE_METHODS, pathPattern, writePermissionCode));
    }

    @Getter
    private static class PermissionRule {
        private final Set<HttpMethod> methods;
        private final String pathPattern;
        private final String permissionCode;

        private PermissionRule(Set<HttpMethod> methods, String pathPattern, String permissionCode) {
            this.methods = methods;
            this.pathPattern = pathPattern;
            this.permissionCode = permissionCode;
        }

        private boolean matches(HttpMethod method, String path, AntPathMatcher matcher) {
            return method != null && methods.contains(method) && matcher.match(pathPattern, path);
        }
    }
}
