package com.mosquito.project.permission;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 审批模板一致性校验服务
 * 在应用启动时校验审批模板的编码、节点顺序、审批角色等是否符合预期
 */
@Service
@ConditionalOnProperty(name = "app.approval.template-check-enabled", havingValue = "true", matchIfMissing = true)
public class ApprovalTemplateConsistencyService {

    private static final Logger log = LoggerFactory.getLogger(ApprovalTemplateConsistencyService.class);

    private final ApprovalFlowRepository flowRepository;
    private final RoleRepository roleRepository;
    private final ObjectMapper objectMapper;

    @Autowired
    public ApprovalTemplateConsistencyService(
            ApprovalFlowRepository flowRepository,
            RoleRepository roleRepository,
            ObjectMapper objectMapper) {
        this.flowRepository = flowRepository;
        this.roleRepository = roleRepository;
        this.objectMapper = objectMapper;
    }

    /**
     * 审批模板预期配置（可配置化）
     * 格式: trigger_event -> 预期配置
     * 与迁移脚本对齐：V49/V50/V55/V58/V60/V69
     * 覆盖 ApprovalFlowService.processAfterApproval 中的所有 bizType
     */
    private static final Map<String, ApprovalTemplateSpec> EXPECTED_TEMPLATES = Map.ofEntries(
            // 活动相关 (V49/V50/V60/V69)
            Map.entry("ACTIVITY_CREATE", new ApprovalTemplateSpec("ACTIVITY_CREATE", "活动创建审批", 1,
                    List.of(new NodeSpec(1, "运营经理审批", "ROLE", List.of("operation_manager"))))),
            Map.entry("ACTIVITY_UPDATE", new ApprovalTemplateSpec("ACTIVITY_UPDATE", "活动更新审批", 1,
                    List.of(new NodeSpec(1, "运营经理审批", "ROLE", List.of("operation_manager"))))),
            Map.entry("ACTIVITY_DELETE", new ApprovalTemplateSpec("ACTIVITY_DELETE", "活动删除审批", 1,
                    List.of(new NodeSpec(1, "运营经理审批", "ROLE", List.of("operation_manager"))))),
            Map.entry("ACTIVITY_PUBLISH", new ApprovalTemplateSpec("ACTIVITY_PUBLISH", "活动发布审批", 1,
                    List.of(new NodeSpec(1, "运营经理审批", "ROLE", List.of("operation_manager"))))),
            // 奖励相关 (V49/V55)
            Map.entry("REWARD_GRANT", new ApprovalTemplateSpec("REWARD_GRANT", "奖励发放审批", 1,
                    List.of(new NodeSpec(1, "运营经理审核", "ROLE", List.of("operation_manager", "finance_manager"))))),
            Map.entry("REWARD_APPLY", new ApprovalTemplateSpec("REWARD_APPLY", "奖励申请审批", 1,
                    List.of(new NodeSpec(1, "运营经理审核", "ROLE", List.of("operation_manager"))))),
            Map.entry("REWARD_APPROVE", new ApprovalTemplateSpec("REWARD_APPROVE", "奖励审批", 1,
                    List.of(new NodeSpec(1, "运营经理审核", "ROLE", List.of("operation_manager"))))),
            Map.entry("HIGH_VALUE_REWARD", new ApprovalTemplateSpec("HIGH_VALUE_REWARD", "大额奖励审批", 2,
                    List.of(
                            new NodeSpec(1, "运营总监审核", "ROLE", List.of("operation_director")),
                            new NodeSpec(2, "财务经理审核", "ROLE", List.of("finance_manager"))
                    ))),
            Map.entry("REWARD_RISK_APPROVAL", new ApprovalTemplateSpec("REWARD_RISK_APPROVAL", "奖励风控审批", 1,
                    List.of(new NodeSpec(1, "风控审批", "ROLE", List.of("risk_manager"))))),
            // 奖励风控+财务两级审批 (V49)
            Map.entry("REWARD_RISK_FINANCE_APPROVAL", new ApprovalTemplateSpec("REWARD_RISK_FINANCE_APPROVAL", "奖励风控+财务审批", 2,
                    List.of(
                            new NodeSpec(1, "风控审批", "ROLE", List.of("risk_manager")),
                            new NodeSpec(2, "财务审批", "ROLE", List.of("finance_manager"))
                    ))),
            // 奖励风控+财务+总监三级审批 (V49)
            Map.entry("REWARD_RISK_FINANCE_DIRECTOR_APPROVAL", new ApprovalTemplateSpec("REWARD_RISK_FINANCE_DIRECTOR_APPROVAL", "奖励风控+财务+总监审批", 3,
                    List.of(
                            new NodeSpec(1, "风控审批", "ROLE", List.of("risk_manager")),
                            new NodeSpec(2, "财务审批", "ROLE", List.of("finance_manager")),
                            new NodeSpec(3, "总监审批", "ROLE", List.of("operation_director"))
                    ))),
            // 用户相关 (V55/V58/V60)
            Map.entry("USER_FREEZE", new ApprovalTemplateSpec("USER_FREEZE", "用户冻结审批", 1,
                    List.of(new NodeSpec(1, "客服主管审批", "ROLE", List.of("cs_manager"))))),
            Map.entry("USER_UNFREEZE", new ApprovalTemplateSpec("USER_UNFREEZE", "用户解冻审批", 2,
                    List.of(
                            new NodeSpec(1, "客服主管审批", "ROLE", List.of("cs_manager")),
                            new NodeSpec(2, "风控经理审批", "ROLE", List.of("risk_manager"))
                    ))),
            Map.entry("USER_DELETE", new ApprovalTemplateSpec("USER_DELETE", "用户删除审批", 2,
                    List.of(
                            new NodeSpec(1, "客服主管审核", "ROLE", List.of("cs_manager")),
                            new NodeSpec(2, "运营总监审核", "ROLE", List.of("operation_director"))
                    ))),
            // 角色相关 (V49/V50/V60)
            Map.entry("ROLE_CHANGE", new ApprovalTemplateSpec("ROLE_CHANGE", "角色变更审批", 1,
                    List.of(new NodeSpec(1, "超级管理员审核", "ROLE", List.of("super_admin"))))),
            Map.entry("ROLE_CREATE", new ApprovalTemplateSpec("ROLE_CREATE", "角色创建审批", 1,
                    List.of(new NodeSpec(1, "超级管理员审核", "ROLE", List.of("super_admin"))))),
            Map.entry("ROLE_UPDATE", new ApprovalTemplateSpec("ROLE_UPDATE", "角色更新审批", 1,
                    List.of(new NodeSpec(1, "超级管理员审核", "ROLE", List.of("super_admin"))))),
            Map.entry("ROLE_DELETE", new ApprovalTemplateSpec("ROLE_DELETE", "角色删除审批", 1,
                    List.of(new NodeSpec(1, "超级管理员审核", "ROLE", List.of("super_admin"))))),
            // 权限相关 (V55/V81)
            Map.entry("PERMISSION_CHANGE", new ApprovalTemplateSpec("PERMISSION_CHANGE", "权限变更审批", 1,
                    List.of(new NodeSpec(1, "系统管理员审核", "ROLE", List.of("system_admin"))))),
            Map.entry("PERMISSION_ASSIGN", new ApprovalTemplateSpec("PERMISSION_ASSIGN", "权限分配审批", 1,
                    List.of(new NodeSpec(1, "系统管理员审核", "ROLE", List.of("system_admin"))))),
            Map.entry("PERMISSION_REVOKE", new ApprovalTemplateSpec("PERMISSION_REVOKE", "权限撤销审批", 1,
                    List.of(new NodeSpec(1, "系统管理员审核", "ROLE", List.of("system_admin"))))),
            // 风控规则相关 (V60)
            Map.entry("RISK_RULE_CREATE", new ApprovalTemplateSpec("RISK_RULE_CREATE", "风控规则创建审批", 2,
                    List.of(
                            new NodeSpec(1, "风控经理审核", "ROLE", List.of("risk_manager")),
                            new NodeSpec(2, "运营总监审核", "ROLE", List.of("operation_director"))
                    ))),
            Map.entry("RISK_RULE_UPDATE", new ApprovalTemplateSpec("RISK_RULE_UPDATE", "风控规则更新审批", 2,
                    List.of(
                            new NodeSpec(1, "风控经理审核", "ROLE", List.of("risk_manager")),
                            new NodeSpec(2, "运营总监审核", "ROLE", List.of("operation_director"))
                    ))),
            Map.entry("RISK_RULE_DELETE", new ApprovalTemplateSpec("RISK_RULE_DELETE", "风控规则删除审批", 2,
                    List.of(
                            new NodeSpec(1, "风控经理审核", "ROLE", List.of("risk_manager")),
                            new NodeSpec(2, "运营总监审核", "ROLE", List.of("operation_director"))
                    ))),
            // API Key相关 (V55)
            Map.entry("API_KEY_CREATE", new ApprovalTemplateSpec("API_KEY_CREATE", "API Key创建审批", 1,
                    List.of(new NodeSpec(1, "系统管理员审核", "ROLE", List.of("system_admin"))))),
            Map.entry("API_KEY_UPDATE", new ApprovalTemplateSpec("API_KEY_UPDATE", "API Key更新审批", 1,
                    List.of(new NodeSpec(1, "系统管理员审核", "ROLE", List.of("system_admin"))))),
            Map.entry("API_KEY_DELETE", new ApprovalTemplateSpec("API_KEY_DELETE", "API Key删除审批", 1,
                    List.of(new NodeSpec(1, "系统管理员审核", "ROLE", List.of("system_admin"))))),
            Map.entry("API_KEY_APPLY", new ApprovalTemplateSpec("API_KEY_APPLY", "API Key申请审批", 1,
                    List.of(new NodeSpec(1, "系统管理员审核", "ROLE", List.of("system_admin"))))),
            // 系统配置 (V55)
            Map.entry("SYSTEM_CONFIG", new ApprovalTemplateSpec("SYSTEM_CONFIG", "系统配置审批", 2,
                    List.of(
                            new NodeSpec(1, "系统管理员审核", "ROLE", List.of("system_admin")),
                            new NodeSpec(2, "超级管理员审核", "ROLE", List.of("super_admin"))
                    ))),
            // 部门变更 (V55)
            Map.entry("DEPARTMENT_CHANGE", new ApprovalTemplateSpec("DEPARTMENT_CHANGE", "部门变更审批", 1,
                    List.of(new NodeSpec(1, "运营总监审核", "ROLE", List.of("operation_director")))))
    );

    @PostConstruct
    public void validateApprovalTemplates() {
        log.info("开始审批模板一致性校验...");
        List<String> errors = new ArrayList<>();
        List<String> warnings = new ArrayList<>();

        try {
            // 获取所有审批模板
            List<SysApprovalFlow> allFlows = flowRepository.findAll();
            log.info("找到 {} 个审批模板", allFlows.size());

            // 校验每个模板
            for (SysApprovalFlow flow : allFlows) {
                String triggerEvent = flow.getTriggerEvent();
                ApprovalTemplateSpec spec = EXPECTED_TEMPLATES.get(triggerEvent);

                if (spec == null) {
                    warnings.add("模板 [" + triggerEvent + "] 无预期配置，跳过校验");
                    continue;
                }

                // 校验flow_name
                if (!spec.flowName.equals(flow.getFlowName())) {
                    errors.add(String.format("模板 [%s] 名称不匹配: 预期=%s, 实际=%s",
                            triggerEvent, spec.flowName, flow.getFlowName()));
                }

                // 校验节点
                if (flow.getNodes() != null && !flow.getNodes().isEmpty()) {
                    try {
                        List<JsonNode> nodes = objectMapper.readValue(flow.getNodes(),
                                objectMapper.getTypeFactory().constructCollectionType(List.class, JsonNode.class));

                        // 校验节点数量
                        if (nodes.size() != spec.nodeCount) {
                            errors.add(String.format("模板 [%s] 节点数量不匹配: 预期=%d, 实际=%d",
                                    triggerEvent, spec.nodeCount, nodes.size()));
                        }

                        // 校验每个节点
                        for (int i = 0; i < Math.min(nodes.size(), spec.nodes.size()); i++) {
                            JsonNode node = nodes.get(i);
                            NodeSpec expectedNode = spec.nodes.get(i);

                            // 校验节点名称
                            String nodeName = node.has("nodeName") ? node.get("nodeName").asText() : "";
                            if (!expectedNode.nodeName.equals(nodeName)) {
                                errors.add(String.format("模板 [%s] 节点[%d] 名称不匹配: 预期=%s, 实际=%s",
                                        triggerEvent, i + 1, expectedNode.nodeName, nodeName));
                            }

                            // 校验审批人类型
                            String approverType = node.has("approverType") ? node.get("approverType").asText() : "";
                            if (!expectedNode.approverType.equals(approverType)) {
                                errors.add(String.format("模板 [%s] 节点[%d] 审批人类型不匹配: 预期=%s, 实际=%s",
                                        triggerEvent, i + 1, expectedNode.approverType, approverType));
                            }

                            // 校验审批人角色
                            if (node.has("approverCodes")) {
                                JsonNode approverCodes = node.get("approverCodes");
                                List<String> actualRoles = new ArrayList<>();
                                for (JsonNode code : approverCodes) {
                                    actualRoles.add(code.asText());
                                }
                                if (!new HashSet<>(expectedNode.approverCodes).containsAll(actualRoles)) {
                                    errors.add(String.format("模板 [%s] 节点[%d] 审批角色不匹配: 预期包含%s, 实际=%s",
                                            triggerEvent, i + 1, expectedNode.approverCodes, actualRoles));
                                }
                            }
                        }
                    } catch (JsonProcessingException e) {
                        errors.add("模板 [" + triggerEvent + "] nodes解析失败: " + e.getMessage());
                    }
                } else {
                    errors.add("模板 [" + triggerEvent + "] 无节点配置");
                }
            }

            // 检查缺失的模板
            for (String triggerEvent : EXPECTED_TEMPLATES.keySet()) {
                boolean exists = allFlows.stream()
                        .anyMatch(f -> f.getTriggerEvent().equals(triggerEvent));
                if (!exists) {
                    errors.add("缺失预期模板: [" + triggerEvent + "]");
                }
            }

            // 输出结果
            if (!errors.isEmpty()) {
                log.error("========== 审批模板校验失败 ==========");
                for (String error : errors) {
                    log.error("  [ERROR] {}", error);
                }
                log.error("修复建议: 运行数据库迁移脚本或手动修正模板配置");
            }

            if (!warnings.isEmpty()) {
                log.warn("========== 审批模板校验警告 ==========");
                for (String warning : warnings) {
                    log.warn("  [WARN] {}", warning);
                }
            }

            if (errors.isEmpty() && warnings.isEmpty()) {
                log.info("========== 审批模板校验通过 ==========");
            }

        } catch (Exception e) {
            log.error("审批模板校验执行失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 审批模板规格定义
     */
    private static class ApprovalTemplateSpec {
        String triggerEvent;
        String flowName;
        int nodeCount;
        List<NodeSpec> nodes;

        ApprovalTemplateSpec(String triggerEvent, String flowName, int nodeCount, List<NodeSpec> nodes) {
            this.triggerEvent = triggerEvent;
            this.flowName = flowName;
            this.nodeCount = nodeCount;
            this.nodes = nodes;
        }
    }

    /**
     * 审批节点规格定义
     */
    private static class NodeSpec {
        int nodeIndex;
        String nodeName;
        String approverType;
        List<String> approverCodes;

        NodeSpec(int nodeIndex, String nodeName, String approverType, List<String> approverCodes) {
            this.nodeIndex = nodeIndex;
            this.nodeName = nodeName;
            this.approverType = approverType;
            this.approverCodes = approverCodes;
        }
    }
}
