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

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.njcn.gather.icd.mapping.component.MappingResponseConverter;
import com.njcn.gather.icd.mapping.pojo.dto.GenerateFromIcdCommand;
import com.njcn.gather.icd.mapping.pojo.dto.IndexBindingCommand;
import com.njcn.gather.icd.mapping.pojo.dto.IndexSelectionGroupCommand;
import com.njcn.gather.icd.mapping.pojo.vo.IndexCandidateReportItemResponse;
import com.njcn.gather.icd.mapping.pojo.vo.IndexCandidateResponse;
import com.njcn.gather.icd.mapping.pojo.vo.MappingTaskResponse;
import com.njcn.gather.icd.mapping.service.MappingTaskService;
import org.springframework.boot.Banner;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * `getIcdMmsJson` 本地调试入口。
 *
 * 使用方式：
 * 1. 先修改 ICD_FILE_PATH 指向本地真实 ICD/SCD 文件。
 * 2. 直接运行 main，先观察第一次调试返回的 indexCandidates。
 * 3. 按第一次返回结果补齐 buildSecondStepSelection() 中的绑定关系。
 * 4. 把 RUN_SECOND_STEP 改成 true，再次运行 main 获取最终 mappingJson。
 */
public class GetIcdMmsJsonDebugRunner {

    /** 本地 ICD/SCD 文件路径，运行前请改成真实文件。 */
    private static final String ICD_FILE_PATH = "D:/temp/demo.icd";

    /** 调试时可固定版本号，便于对比输出。 */
    private static final String VERSION = "20260421";

    /** 调试作者标识。 */
    private static final String AUTHOR = "debug-user";

    /** 是否输出格式化 JSON，便于人工查看。 */
    private static final boolean PRETTY_JSON = true;

    /** 是否把生成结果写入磁盘。 */
    private static final boolean SAVE_TO_DISK = false;

    /** saveToDisk=true 时使用的输出目录。 */
    private static final String OUTPUT_DIR = "D:/temp/mms-output";

    /**
     * 第二次正式生成开关。
     * 默认先只跑第一次，确认 groupKey/reportName/dataSetName/lnInst 候选值后再打开。
     */
    private static final boolean RUN_SECOND_STEP = false;

    public static void main(String[] args) {
        try (ConfigurableApplicationContext context = new SpringApplicationBuilder(DebugApplication.class)
                .web(WebApplicationType.NONE)
                .bannerMode(Banner.Mode.OFF)
                .logStartupInfo(false)
                .run(args)) {
            MappingTaskService mappingTaskService = context.getBean(MappingTaskService.class);
            MappingResponseConverter responseConverter = context.getBean(MappingResponseConverter.class);
            ObjectMapper objectMapper = createObjectMapper();

            MappingTaskResponse firstResponse = debugNeedIndexSelection(mappingTaskService, responseConverter);
            printResponse("第一次调试：获取索引候选", firstResponse, objectMapper);
            printIndexCandidateSummary(firstResponse);

            if (!RUN_SECOND_STEP) {
                System.out.println("第二次调试未开启。请先根据第一次返回结果补齐 buildSecondStepSelection()，再把 RUN_SECOND_STEP 改成 true。");
                return;
            }

            MappingTaskResponse secondResponse = debugGenerateMapping(mappingTaskService, responseConverter);
            printResponse("第二次调试：生成 MMS JSON", secondResponse, objectMapper);
        } catch (Exception ex) {
            throw new IllegalStateException("getIcdMmsJson 调试失败：" + ex.getMessage(), ex);
        }
    }

    /**
     * 第一次调试：不传 indexSelection，只获取 icdDocument 和 indexCandidates。
     */
    private static MappingTaskResponse debugNeedIndexSelection(MappingTaskService mappingTaskService,
                                                               MappingResponseConverter responseConverter) {
        GenerateFromIcdCommand command = buildBaseCommand();
        return responseConverter.fromSubmitResult(mappingTaskService.getIcdMmsJson(command));
    }

    /**
     * 第二次调试：补齐 indexSelection 后直接生成最终 mappingJson。
     */
    private static MappingTaskResponse debugGenerateMapping(MappingTaskService mappingTaskService,
                                                            MappingResponseConverter responseConverter) {
        List<IndexSelectionGroupCommand> selectionGroups = buildSecondStepSelection();
        if (selectionGroups.isEmpty()) {
            throw new IllegalArgumentException("第二次调试缺少 indexSelection，请先补齐 buildSecondStepSelection()");
        }

        GenerateFromIcdCommand command = buildBaseCommand();
        command.getIndexSelection().addAll(selectionGroups);
        return responseConverter.fromSubmitResult(mappingTaskService.getIcdMmsJson(command));
    }

    /**
     * 组装调试用基础命令，等价于接口中的 request 基础参数。
     */
    private static GenerateFromIcdCommand buildBaseCommand() {
        Path icdPath = Paths.get(ICD_FILE_PATH);
        if (!Files.exists(icdPath)) {
            throw new IllegalArgumentException("ICD 文件不存在：" + icdPath.toAbsolutePath());
        }

        try {
            GenerateFromIcdCommand command = new GenerateFromIcdCommand();
            command.setFileName(icdPath.getFileName().toString());
            command.setFileBytes(Files.readAllBytes(icdPath));
            command.setVersion(VERSION);
            command.setAuthor(AUTHOR);
            command.setPrettyJson(PRETTY_JSON);
            command.setSaveToDisk(SAVE_TO_DISK);
            command.setOutputDir(OUTPUT_DIR);
            return command;
        } catch (Exception ex) {
            throw new IllegalArgumentException("读取 ICD 文件失败：" + ex.getMessage(), ex);
        }
    }

    /**
     * 第二次调试的索引绑定示例。
     *
     * 注意：
     * 1. groupKey/groupDesc/reportName/dataSetName/lnInst 必须使用第一次返回的真实值。
     * 2. 下面示例仅作占位，默认不参与运行。
     */
    private static List<IndexSelectionGroupCommand> buildSecondStepSelection() {
        List<IndexSelectionGroupCommand> groups = new ArrayList<IndexSelectionGroupCommand>();

        // 示例：
        // IndexSelectionGroupCommand group = createSelectionGroup("HARM__DSSTHARM", "谐波数据");
        // group.getBindings().add(createBinding("brcbStHarm", "dsStHarm", "A相", "1"));
        // group.getBindings().add(createBinding("brcbStHarm", "dsStHarm", "B相", "2"));
        // group.getBindings().add(createBinding("brcbStHarm", "dsStHarm", "C相", "3"));
        // groups.add(group);

        return groups;
    }

    private static IndexSelectionGroupCommand createSelectionGroup(String groupKey, String groupDesc) {
        IndexSelectionGroupCommand group = new IndexSelectionGroupCommand();
        group.setGroupKey(groupKey);
        group.setGroupDesc(groupDesc);
        return group;
    }

    private static IndexBindingCommand createBinding(String reportName,
                                                     String dataSetName,
                                                     String label,
                                                     String lnInst) {
        IndexBindingCommand binding = new IndexBindingCommand();
        binding.setReportName(reportName);
        binding.setDataSetName(dataSetName);
        binding.setLabel(label);
        binding.setLnInst(lnInst);
        return binding;
    }

    /**
     * 控制台输出候选摘要，方便把第一次返回值填回第二次调试配置。
     */
    private static void printIndexCandidateSummary(MappingTaskResponse response) {
        if (response == null || response.getIndexCandidates() == null || response.getIndexCandidates().isEmpty()) {
            return;
        }

        System.out.println("===== 索引候选摘要 =====");
        for (IndexCandidateResponse candidate : response.getIndexCandidates()) {
            System.out.println("groupKey=" + candidate.getGroupKey() + ", groupDesc=" + candidate.getGroupDesc());
            if (candidate.getReports() == null) {
                continue;
            }
            for (IndexCandidateReportItemResponse report : candidate.getReports()) {
                System.out.println("  reportName=" + report.getReportName()
                        + ", dataSetName=" + report.getDataSetName()
                        + ", availableLnInstValues=" + report.getAvailableLnInstValues());
            }
        }
    }

    private static void printResponse(String title, MappingTaskResponse response, ObjectMapper objectMapper) {
        try {
            System.out.println();
            System.out.println("===== " + title + " =====");
            System.out.println(objectMapper.writeValueAsString(response));
        } catch (Exception ex) {
            throw new IllegalArgumentException("打印调试响应失败：" + ex.getMessage(), ex);
        }
    }

    private static ObjectMapper createObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        return objectMapper;
    }

    @SpringBootApplication(scanBasePackages = "com.njcn.gather.icd.mapping")
    public static class DebugApplication {
    }
}
