package top.r3944realms.docchecktoolrefactored.core;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import top.r3944realms.docchecktoolrefactored.System;
import top.r3944realms.docchecktoolrefactored.ThreadPoolManager;
import top.r3944realms.docchecktoolrefactored.util.LoggerMarker;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Slf4j
public class AddressFileComparator {

    public enum CompareMode {
        PAGE_LEVEL,  // 页面级比较
        FILE_LEVEL   // 文件级比较
    }
    // 进度回调接口
    public interface ProgressCallback {
        default void onPhaseStarted(Phase phase) {}
        default void onPhaseProgress(Phase phase, int current, int total) {}
        default void onPhaseCompleted(Phase phase) {}
    }

    // 比较阶段
    public enum Phase {
        READ_PHYSICAL_CSV,
        READ_LOGICAL_CSV,
        COMPARE_FORWARD,
        COMPARE_BACKWARD
    }
    @Getter
    public static class ComparisonResult {
        private final int physicalRecordsCount;  // 物理文件记录数
        private final int logicalRecordsCount;   // 逻辑文件记录数
        private final List<String> forwardComparisonResults;     // 正向比较文件名缺失结果
        private final List<String> backwardComparisonResults;    // 反向比较文件名缺失结果
        private final List<String> pathMismatchResults;          // 路径不一致的结果
        private final List<String> pageCountMismatchResults;     // 页数不一致的结果（仅文件级比较使用）

        public ComparisonResult(int physicalRecordsCount,
                                int logicalRecordsCount,
                                List<String> forwardResults,
                                List<String> backwardResults,
                                List<String> pathMismatchResults,
                                List<String> pageCountMismatchResults) {
            this.physicalRecordsCount = physicalRecordsCount;
            this.logicalRecordsCount = logicalRecordsCount;
            this.forwardComparisonResults = forwardResults;
            this.backwardComparisonResults = backwardResults;
            this.pathMismatchResults = pathMismatchResults;
            this.pageCountMismatchResults = pageCountMismatchResults;
        }
        public static @NotNull String generateResult(AddressFileComparator.CompareMode compareMode, AddressFileComparator.ComparisonResult result) {
            StringBuilder resultText = new StringBuilder();
            resultText.append("读取物理地址文件记录数: ").append(result.getPhysicalRecordsCount()).append("\n");
            resultText.append("读取逻辑地址文件记录数: ").append(result.getLogicalRecordsCount()).append("\n\n");

            if (!result.getPathMismatchResults().isEmpty()) {
                resultText.append("文件名相同但路径不一致的记录数量: ")
                        .append(result.getPathMismatchResults().size()).append("\n");
                result.getPathMismatchResults().forEach(s -> resultText.append("\t").append(s).append("\n"));
            } else resultText.append("没有路径错误\n\n");

            if (compareMode == AddressFileComparator.CompareMode.FILE_LEVEL &&
                    !result.getPageCountMismatchResults().isEmpty()) {
                resultText.append("文件名和路径相同但页数不一致的记录数量: ")
                        .append(result.getPageCountMismatchResults().size()).append("\n");
                result.getPageCountMismatchResults().forEach(s -> resultText.append("\t").append(s).append("\n"));
            }

            if (!result.getForwardComparisonResults().isEmpty()) {
                resultText.append("物理文件在逻辑文件中未找到的记录数量: ")
                        .append(result.getForwardComparisonResults().size()).append("\n");
                result.getForwardComparisonResults().forEach(s -> resultText.append("\t").append(s).append("\n"));
            } else resultText.append("没有物理存在而逻辑不存在的文件\n\n");

            if (!result.getBackwardComparisonResults().isEmpty()) {
                resultText.append("逻辑文件在物理文件中未找到的记录数量: ")
                        .append(result.getBackwardComparisonResults().size()).append("\n");
                result.getBackwardComparisonResults().forEach(s -> resultText.append("\t").append(s).append("\n"));
            } else resultText.append("没有逻辑存在而物理不存在的文件\n");

            if (result.getPathMismatchResults().isEmpty() &&
                    result.getForwardComparisonResults().isEmpty() &&
                    result.getBackwardComparisonResults().isEmpty()) {
                resultText.append("\n所有文件比对一致，无差异。\n");
            }

            return resultText.toString();
        }
        public static String generateComparisonResults(ComparisonResult result, CompareMode compareMode) {
            return generateComparisonResults(
                    result.physicalRecordsCount,
                    result.logicalRecordsCount,
                    result.forwardComparisonResults,
                    result.backwardComparisonResults,
                    result.pathMismatchResults,
                    result.pageCountMismatchResults,
                    compareMode
            );
        }

        private static String generateComparisonResults(int physicalCount, int logicalCount,
                                                        List<String> forwardResults, List<String> backwardResults,
                                                        List<String> pathMismatchResults, List<String> pageCountMismatchResults,
                                                        CompareMode compareMode) {
            StringBuilder sb = new StringBuilder();

            sb.append("=== 文件比较结果 ===\n");
            sb.append("物理地址文件记录数: ").append(physicalCount).append("\n");
            sb.append("逻辑地址文件记录数: ").append(logicalCount).append("\n");

            if (pathMismatchResults.isEmpty()) {
                sb.append("没有路径错误\n");
            } else {
                sb.append("文件名相同但路径不一致的记录数量: ").append(pathMismatchResults.size()).append("\n");
                pathMismatchResults.forEach(result -> sb.append("\t").append(result).append("\n"));
            }

            if (compareMode == CompareMode.FILE_LEVEL) {
                if (pageCountMismatchResults.isEmpty()) {
                    sb.append("没有页数错误\n");
                } else {
                    sb.append("文件名和路径相同但页数不一致的记录数量: ")
                            .append(pageCountMismatchResults.size()).append("\n");
                    pageCountMismatchResults.forEach(result -> sb.append("\t").append(result).append("\n"));
                }
            }

            if (forwardResults.isEmpty()) {
                sb.append("没有物理存在而逻辑不存在的文件\n");
            } else {
                sb.append("物理文件在逻辑文件中未找到的记录数量: ").append(forwardResults.size()).append("\n");
                forwardResults.forEach(result -> sb.append("\t").append(result).append("\n"));
            }

            if (backwardResults.isEmpty()) {
                sb.append("没有逻辑存在而物理不存在的文件\n");
            } else {
                sb.append("逻辑文件在物理文件中未找到的记录数量: ").append(backwardResults.size()).append("\n");
                backwardResults.forEach(result -> sb.append("\t").append(result).append("\n"));
            }

            sb.append("=== 比较完成 ===");

            return sb.toString();
        }

    }
    private final ExecutorService executor;
    public AddressFileComparator(int threadPoolSize) {
        this.executor = ThreadPoolManager.createPool("address-comparator", threadPoolSize);
    }

    public AddressFileComparator() {
        this.executor = ThreadPoolManager.createPool("address-comparator", System.getAvailableProcessors());
    }
    @Setter
    private ProgressCallback progressCallback;


    // 安全调用回调方法
    private void safeOnPhaseStarted(Phase phase) {
        if (progressCallback != null) {
            progressCallback.onPhaseStarted(phase);
        }
    }

    private void safeOnPhaseProgress(Phase phase, int current, int total) {
        if (progressCallback != null) {
            progressCallback.onPhaseProgress(phase, current, total);
        }
    }

    private void safeOnPhaseCompleted(Phase phase) {
        if (progressCallback != null) {
            progressCallback.onPhaseCompleted(phase);
        }
    }
    public void shutdown() {
        executor.shutdown(); // 先尝试正常关闭
        try {
            if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
                executor.shutdownNow(); // 强制关闭
                // 等待一段时间让任务响应中断
                if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
                    log.error(LoggerMarker.DEBUG_MARKER, "线程池无法正常关闭");
                }
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    public void safeShutdown() {
        if (!executor.isShutdown()) {
            shutdown();
        }
    }

    public CompletableFuture<ComparisonResult> compareFiles(String physicalFilePath, String logicalFilePath, CompareMode compareMode) {
        // 读取物理文件
        CompletableFuture<List<String[]>> physicalFuture = CompletableFuture.supplyAsync(() -> {
            safeOnPhaseStarted(Phase.READ_PHYSICAL_CSV);
            List<String[]> list = readCSV(physicalFilePath, progressCallback, Phase.READ_PHYSICAL_CSV);
            safeOnPhaseCompleted(Phase.READ_PHYSICAL_CSV);
            return list;
        }, executor);

        // 读取逻辑文件
        CompletableFuture<List<String[]>> logicalFuture = CompletableFuture.supplyAsync(() -> {
            safeOnPhaseStarted(Phase.READ_LOGICAL_CSV);
            List<String[]> list = readCSV(logicalFilePath, progressCallback, Phase.READ_LOGICAL_CSV);
            safeOnPhaseCompleted(Phase.READ_LOGICAL_CSV);
            return list;
        }, executor);

        // 两个 CSV 读取完成后进行比较
        return physicalFuture.thenCombineAsync(logicalFuture, (physicalRecords, logicalRecords) -> {
            int physicalCount = physicalRecords.size();
            int logicalCount = logicalRecords.size();

            // 线程安全集合
            List<String> forwardComparisonResults = Collections.synchronizedList(new ArrayList<>());
            List<String> backwardComparisonResults = Collections.synchronizedList(new ArrayList<>());
            List<String> pathMismatchResults = Collections.synchronizedList(new ArrayList<>());
            List<String> pageCountMismatchResults = Collections.synchronizedList(new ArrayList<>());

            Map<String, String[]> logicalMap = logicalRecords.parallelStream()
                    .filter(r -> r.length >= (compareMode == CompareMode.FILE_LEVEL ? 3 : 2))
                    .collect(Collectors.toConcurrentMap(r -> r[0], r -> r));

            // 正向比较
            safeOnPhaseStarted(Phase.COMPARE_FORWARD);
            AtomicInteger forwardCounter = new AtomicInteger(0);
            physicalRecords.parallelStream()
                    .filter(r -> r.length >= (compareMode == CompareMode.FILE_LEVEL ? 3 : 2))
                    .forEach(physicalRecord -> {
                        String physicalFileName = physicalRecord[0];
                        String physicalAddress = physicalRecord[1];
                        String physicalPageCount = compareMode == CompareMode.FILE_LEVEL ? physicalRecord[2] : null;

                        String[] logicalRecord = logicalMap.get(physicalFileName);
                        if (logicalRecord == null) {
                            String result = "文件名=" + physicalFileName + ", 物理地址=" + physicalAddress;
                            if (compareMode == CompareMode.FILE_LEVEL && physicalPageCount != null) {
                                result += ", 物理页数=" + physicalPageCount;
                            }
                            forwardComparisonResults.add(result);
                        } else {
                            if (!physicalAddress.equals(logicalRecord[1])) {
                                pathMismatchResults.add("文件名=" + physicalFileName +
                                        ", 物理地址=" + physicalAddress +
                                        ", 逻辑地址=" + logicalRecord[1]);
                            }
                            if (compareMode == CompareMode.FILE_LEVEL &&
                                    physicalPageCount != null && !physicalPageCount.equals(logicalRecord[2])) {
                                pageCountMismatchResults.add("文件名=" + physicalFileName +
                                        ", 物理地址=" + physicalAddress +
                                        ", 逻辑地址=" + logicalRecord[1] +
                                        ", 物理页数=" + physicalPageCount +
                                        ", 逻辑页数=" + logicalRecord[2]);
                            }
                        }

                        int done = forwardCounter.incrementAndGet();
                        safeOnPhaseProgress(Phase.COMPARE_FORWARD, done, physicalRecords.size());
                    });
            safeOnPhaseCompleted(Phase.COMPARE_FORWARD);

            // 反向比较
            safeOnPhaseStarted(Phase.COMPARE_BACKWARD);
            AtomicInteger backwardCounter = new AtomicInteger(0);
            Map<String, String[]> physicalMap = physicalRecords.parallelStream()
                    .filter(r -> r.length >= (compareMode == CompareMode.FILE_LEVEL ? 3 : 2))
                    .collect(Collectors.toConcurrentMap(r -> r[0], r -> r));

            logicalRecords.parallelStream()
                    .filter(r -> r.length >= (compareMode == CompareMode.FILE_LEVEL ? 3 : 2))
                    .forEach(logicalRecord -> {
                        String logicalFileName = logicalRecord[0];
                        String logicalAddress = logicalRecord[1];
                        String logicalPageCount = compareMode == CompareMode.FILE_LEVEL ? logicalRecord[2] : null;

                        if (!physicalMap.containsKey(logicalFileName)) {
                            String result = "文件名=" + logicalFileName + ", 逻辑地址=" + logicalAddress;
                            if (compareMode == CompareMode.FILE_LEVEL && logicalPageCount != null) {
                                result += ", 逻辑页数=" + logicalPageCount;
                            }
                            backwardComparisonResults.add(result);
                        }

                        int done = backwardCounter.incrementAndGet();
                        safeOnPhaseProgress(Phase.COMPARE_BACKWARD, done, logicalRecords.size());
                    });
            safeOnPhaseCompleted(Phase.COMPARE_BACKWARD);

            return new ComparisonResult(
                    physicalCount,
                    logicalCount,
                    forwardComparisonResults,
                    backwardComparisonResults,
                    pathMismatchResults,
                    pageCountMismatchResults
            );
        }, executor);
    }

    private List<String[]> readCSV(String filePath, ProgressCallback callback, Phase phase) {
        List<String[]> records = new ArrayList<>();
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                log.error(LoggerMarker.RELEASE_MARKER, "{} CSV文件不存在: {}", phase, filePath);
                return records;
            }

            BufferedReader reader = new BufferedReader(new FileReader(file));
            List<String> allLines = reader.lines().skip(1).toList(); // 跳过标题行
            reader.close();

            int total = allLines.size();
            AtomicInteger counter = new AtomicInteger(0);
            for (String line : allLines) {
                records.add(line.split(","));
                int done = counter.incrementAndGet();
                if (done % 100 == 0 || done == total) {  // 每100行或结束更新
                    callback.onPhaseProgress(phase, done, total);
                }
            }
        } catch (Exception e) {
            log.error(LoggerMarker.RELEASE_MARKER, "{} CSV文件读取出错: {}", phase, e.getMessage(), e);
        }
        return records;
    }


}
