package com.aicheck.analyzer;

import com.aicheck.config.AppConfig;
import com.aicheck.model.ApiEndpoint;
import com.aicheck.model.ClassChangeReport;
import com.aicheck.model.ClassType;
import com.aicheck.parser.ConversionParser;

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 根据变更报告匹配受影响的 HTTP 接口与 Dto→Entity 转换目标。
 */
public class ImpactAnalyzer {
    private final ConversionParser conversionParser = new ConversionParser();

    /**
     * 填充 report 的影响列表；新旧类名均参与匹配；Entity/Model 不匹配接口。
     */
    public void analyze(ClassChangeReport report, Map<String, ApiEndpoint> endpointIndex,
                        AppConfig config, Path repoRoot, String newSource, String oldSource) throws IOException {
        Set<String> matchNames = namesForMatching(report);

        if (report.getClassType() != ClassType.ENTITY && report.getClassType() != ClassType.MODEL) {
            matchEndpoints(report, endpointIndex, matchNames);
        }

        if (!config.isDtoEntityConversionEnabled()) {
            return;
        }

        analyzeConversion(report, config, repoRoot, newSource, oldSource, matchNames);
    }

    /** 收集新旧类名用于接口/转换匹配 */
    private Set<String> namesForMatching(ClassChangeReport report) {
        Set<String> names = new LinkedHashSet<>();
        names.add(report.getClassName());
        if (report.getOldClassName() != null && !report.getOldClassName().isBlank()) {
            names.add(report.getOldClassName());
        }
        return names;
    }

    /** 在接口索引中匹配入参/返回类型 */
    private void matchEndpoints(ClassChangeReport report, Map<String, ApiEndpoint> endpointIndex,
                                Set<String> matchNames) {
        List<ApiEndpoint> inputImpacts = new ArrayList<>();
        List<ApiEndpoint> frontendImpacts = new ArrayList<>();

        for (ApiEndpoint endpoint : endpointIndex.values()) {
            if (matchesAnyType(endpoint.getParamTypes(), matchNames)) {
                inputImpacts.add(endpoint);
            }
            if (matchesAnyType(endpoint.getReturnTypes(), matchNames)) {
                frontendImpacts.add(endpoint);
            }
        }

        inputImpacts.forEach(report::addInputImpact);
        frontendImpacts.forEach(report::addFrontendImpact);
    }

    /** 扫描 convert 方法与 BeanUtils.copyProperties 关联的 Entity */
    private void analyzeConversion(ClassChangeReport report, AppConfig config, Path repoRoot,
                                   String newSource, String oldSource, Set<String> matchNames) throws IOException {
        for (String name : matchNames) {
            if (newSource != null && !newSource.isBlank()) {
                conversionParser.findConvertTargetsInClass(newSource, name)
                        .forEach(report::addConversionEntity);
            }
            if (oldSource != null && !oldSource.isBlank() && !oldSource.equals(newSource)) {
                conversionParser.findConvertTargetsInClass(oldSource, name)
                        .forEach(report::addConversionEntity);
            }
            for (String scanDir : config.getConversionScanDirs()) {
                conversionParser.findBeanUtilsTargets(repoRoot.resolve(scanDir), name)
                        .forEach(report::addConversionEntity);
            }
        }
    }

    /** 类型集合中是否包含任一目标类名 */
    private boolean matchesAnyType(Collection<String> types, Set<String> classNames) {
        if (types == null) {
            return false;
        }
        for (String type : types) {
            if (classNames.contains(type)) {
                return true;
            }
        }
        return false;
    }
}
