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.analysis.ValidationResult;
import com.njcn.gather.icd.mapping.pojo.dto.IndexBindingCommand;
import com.njcn.gather.icd.mapping.pojo.dto.IndexSelectionGroupCommand;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 索引绑定校验服务。
 *
 * 校验原则：
 * 1. 只校验用户明确提交的绑定项；
 * 2. 不强制模板中的所有标签都必须配置；
 * 3. label 必须属于当前业务分组的 templateLabels；
 * 4. lnInst 必须属于当前报告对应的 ICD 候选数字。
 */
@Service
public class IndexValidationService {

    /**
     * 校验前端提交的分组绑定是否能落到当前 ICD 候选范围内。
     */
    public ValidationResult validate(IndexAnalysis analysis, List<IndexSelectionGroupCommand> selections) {
        ValidationResult result = new ValidationResult();

        if (analysis == null || analysis.getCandidates() == null || analysis.getCandidates().isEmpty()) {
            result.getProblems().add("当前 ICD 未解析出任何可配置的候选分组");
            return result;
        }

        if (selections == null || selections.isEmpty()) {
            for (IndexCandidate candidate : analysis.getCandidates()) {
                result.getProblems().add(
                        "分组【" + candidate.getGroupDesc() + "】未提交绑定关系，请根据 templateLabels 与 reports[*].availableLnInstValues 完成配置"
                );
            }
            return result;
        }

        for (IndexSelectionGroupCommand selection : selections) {
            IndexCandidate candidate = findCandidate(analysis, selection.getGroupKey(), selection.getGroupDesc());
            if (candidate == null) {
                result.getProblems().add("未找到分组配置：groupKey=" + selection.getGroupKey() + ", groupDesc=" + selection.getGroupDesc());
                continue;
            }

            if (selection.getBindings() == null || selection.getBindings().isEmpty()) {
                result.getProblems().add("分组【" + candidate.getGroupDesc() + "】没有任何绑定关系");
                continue;
            }

            for (IndexBindingCommand binding : selection.getBindings()) {
                validateBinding(candidate, binding, result);
            }
        }

        if (result.getProblems().isEmpty()) {
            result.setValid(true);
        }
        return result;
    }

    /**
     * 校验单条 label + report + lnInst 绑定。
     */
    private void validateBinding(IndexCandidate candidate, IndexBindingCommand binding, ValidationResult result) {
        if (binding == null) {
            result.getProblems().add("存在空的绑定项");
            return;
        }

        if (isBlank(binding.getLabel())) {
            result.getProblems().add("分组【" + candidate.getGroupDesc() + "】存在未填写 label 的绑定项");
        } else if (!candidate.getTemplateLabels().contains(binding.getLabel())) {
            result.getProblems().add("分组【" + candidate.getGroupDesc() + "】中 label【" + binding.getLabel() + "】不在模板候选中");
        }

        IndexCandidateReportItem reportItem = findReport(candidate, binding.getReportName(), binding.getDataSetName());
        if (reportItem == null) {
            result.getProblems().add(
                    "分组【" + candidate.getGroupDesc() + "】中未找到报告：reportName=" + binding.getReportName()
                            + ", dataSetName=" + binding.getDataSetName()
            );
            return;
        }

        if (isBlank(binding.getLnInst())) {
            result.getProblems().add("报告【" + reportItem.getReportName() + "】未填写 lnInst");
        } else if (!reportItem.getAvailableLnInstValues().contains(binding.getLnInst())) {
            result.getProblems().add(
                    "报告【" + reportItem.getReportName() + "】的 lnInst【" + binding.getLnInst() + "】不在可选数字中："
                            + reportItem.getAvailableLnInstValues()
            );
        }
    }

    /**
     * 优先按 groupKey 匹配候选分组，兼容只传 groupDesc 的旧调用。
     */
    private IndexCandidate findCandidate(IndexAnalysis analysis, String groupKey, String groupDesc) {
        for (IndexCandidate candidate : analysis.getCandidates()) {
            if (same(candidate.getGroupKey(), groupKey)) {
                return candidate;
            }
            if (same(candidate.getGroupDesc(), groupDesc)) {
                return candidate;
            }
        }
        return null;
    }

    /**
     * 在候选分组内定位具体报告，dataSetName 为空时只按报告名匹配。
     */
    private IndexCandidateReportItem findReport(IndexCandidate candidate, String reportName, String dataSetName) {
        if (candidate.getReports() == null) {
            return null;
        }
        for (IndexCandidateReportItem item : candidate.getReports()) {
            if (same(item.getReportName(), reportName) && (isBlank(dataSetName) || same(item.getDataSetName(), dataSetName))) {
                return item;
            }
        }
        return null;
    }

    private boolean same(String left, String right) {
        if (left == null && right == null) {
            return true;
        }
        if (left == null || right == null) {
            return false;
        }
        return left.trim().equals(right.trim());
    }

    private boolean isBlank(String value) {
        return value == null || value.trim().isEmpty();
    }
}
