package com.njcn.gather.icd.mapping.component;

import com.njcn.gather.icd.mapping.pojo.bo.analysis.IndexAnalysis;
import com.njcn.gather.icd.mapping.pojo.bo.analysis.IndexCandidate;
import com.njcn.gather.icd.mapping.pojo.bo.analysis.IndexCandidateReportItem;
import com.njcn.gather.icd.mapping.pojo.bo.icd.DataSetNode;
import com.njcn.gather.icd.mapping.pojo.bo.icd.FcdaNode;
import com.njcn.gather.icd.mapping.pojo.bo.icd.IcdDocument;
import com.njcn.gather.icd.mapping.pojo.bo.icd.ReportControlNode;
import com.njcn.gather.icd.mapping.pojo.bo.template.DefaultTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

/**
 * 索引候选分析服务。
 *
 * 按 `DefaultCfg.ReportList` 的业务分组聚合 ICD 中的报告信息，
 * 同时把后续正式生成阶段需要的模板字段一并带入候选结果。
 */
@Service
public class IndexAnalysisService {

    /**
     * 根据 ICD 报告控制块和 DefaultCfg.ReportList 生成索引候选分组。
     */
    public IndexAnalysis analyze(IcdDocument icdDocument, DefaultTemplate template) {
        IndexAnalysis analysis = new IndexAnalysis();
        if (icdDocument == null) {
            analysis.getProblems().add("ICD 文档为空");
            return analysis;
        }
        if (template == null || template.getReportList() == null) {
            analysis.getProblems().add("DefaultCfg.ReportList 为空");
            return analysis;
        }

        // 先按模板分组聚合候选项，而不是按单个报告平铺返回。
        for (DefaultTemplate.ReportCfgItem reportCfg : template.getReportList()) {
            List<ReportControlNode> matchedReports = collectMatchedReports(icdDocument, reportCfg);
            if (matchedReports.isEmpty()) {
                continue;
            }

            IndexCandidate candidate = new IndexCandidate();
            candidate.setGroupKey(buildGroupKey(reportCfg));
            candidate.setGroupDesc(reportCfg.getDesc());
            candidate.setReportCount(matchedReports.size());

            // 把模板中的关键配置直接带入候选对象，避免正式生成阶段再次回查模板。
            candidate.setReportInst(reportCfg.getInst());
            candidate.setSelect(reportCfg.getSelect());
            candidate.setTrgOps(reportCfg.getTrgOps());

            if (reportCfg.getLnInstList() != null) {
                candidate.getTemplateLabels().addAll(reportCfg.getLnInstList());
            }

            for (ReportControlNode reportControl : matchedReports) {
                IndexCandidateReportItem item = new IndexCandidateReportItem();
                item.setReportName(reportControl.getName());
                item.setDataSetName(reportControl.getDataSetName());
                item.setReportDesc(reportCfg.getDesc());
                item.getAvailableLnInstValues().addAll(collectLnInstValues(icdDocument, reportControl.getDataSetName()));
                candidate.getReports().add(item);
            }

            analysis.getCandidates().add(candidate);
        }

        // 检查 ICD 中是否存在未被模板覆盖的报告配置。
        if (icdDocument.getReportControls() != null) {
            for (ReportControlNode reportControl : icdDocument.getReportControls()) {
                if (!isCoveredByTemplate(reportControl, template)) {
                    analysis.getProblems().add(
                            "报告 " + reportControl.getName()
                                    + " 未在 DefaultCfg.ReportList 中匹配到配置；dataSet=" + reportControl.getDataSetName()
                    );
                }
            }
        }

        return analysis;
    }

    /**
     * 收集命中当前模板报告分组 DataSetList 的报告控制块。
     */
    private List<ReportControlNode> collectMatchedReports(IcdDocument icdDocument, DefaultTemplate.ReportCfgItem reportCfg) {
        List<ReportControlNode> result = new ArrayList<ReportControlNode>();
        if (icdDocument.getReportControls() == null || reportCfg.getDataSetList() == null) {
            return result;
        }
        for (ReportControlNode reportControl : icdDocument.getReportControls()) {
            if (reportCfg.getDataSetList().contains(reportControl.getDataSetName())) {
                result.add(reportControl);
            }
        }
        return result;
    }

    /**
     * 判断 ICD 中的报告是否已经被模板 ReportList 覆盖。
     */
    private boolean isCoveredByTemplate(ReportControlNode reportControl, DefaultTemplate template) {
        if (template == null || template.getReportList() == null) {
            return false;
        }
        for (DefaultTemplate.ReportCfgItem reportCfg : template.getReportList()) {
            if (reportCfg.getDataSetList() != null && reportCfg.getDataSetList().contains(reportControl.getDataSetName())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 从指定 DataSet 的 FCDA 中提取可选 lnInst 数字，并按数字优先排序。
     */
    private List<String> collectLnInstValues(IcdDocument icdDocument, String dataSetName) {
        if (icdDocument.getDataSets() == null) {
            return Collections.emptyList();
        }

        DataSetNode dataSetNode = icdDocument.getDataSets().get(dataSetName);
        if (dataSetNode == null || dataSetNode.getFcdas() == null) {
            return Collections.emptyList();
        }

        Set<String> unique = new LinkedHashSet<String>();
        for (FcdaNode fcda : dataSetNode.getFcdas()) {
            if (fcda == null || fcda.getLnInst() == null) {
                continue;
            }
            String lnInst = fcda.getLnInst().trim();
            if (!lnInst.isEmpty()) {
                unique.add(lnInst);
            }
        }

        List<String> result = new ArrayList<String>(unique);
        Collections.sort(result, new Comparator<String>() {
            @Override
            public int compare(String left, String right) {
                try {
                    return Integer.valueOf(left).compareTo(Integer.valueOf(right));
                } catch (Exception ex) {
                    return left.compareTo(right);
                }
            }
        });
        return result;
    }

    /**
     * 构造前端回传使用的稳定分组 key。
     */
    private String buildGroupKey(DefaultTemplate.ReportCfgItem reportCfg) {
        String desc = reportCfg.getDesc() == null ? "GROUP" : reportCfg.getDesc();
        String firstDataSet = (reportCfg.getDataSetList() == null || reportCfg.getDataSetList().isEmpty())
                ? "DEFAULT" : reportCfg.getDataSetList().get(0);
        return normalize(desc) + "__" + normalize(firstDataSet);
    }

    /**
     * 将中文描述和 DataSet 名转换为可比较的 key 片段。
     */
    private String normalize(String value) {
        return value.replaceAll("[^0-9A-Za-z\\u4e00-\\u9fa5]+", "_")
                .replaceAll("_+", "_")
                .replaceAll("^_", "")
                .replaceAll("_$", "")
                .toUpperCase(Locale.ROOT);
    }
}