package com.example.demo.service;

import com.example.demo.model.TaskScheme;
import com.example.demo.model.dto.SchemeCompareDTO;
import com.example.demo.model.enums.SchemeStatus;
import com.example.demo.repository.SchemeRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 任务方案管理服务。
 * <p>
 * 实现集中式/分布式任务方案的统一管理、对比、重构及执行监控能力。
 * </p>
 *
 * @requirement(name="集中式/分布式方案列表展示", id="SRS-TMS-01")
 * 以表格或卡片形式展示所有可用任务方案，支持分页加载。
 *
 * @requirement(name="自定义排序功能", id="SRS-TMS-02")
 * 按生成时间、优先级、成功率等字段升序/降序排列。
 *
 * @requirement(name="方案详情查看", id="SRS-TMS-03")
 * 展示兵力部署、行动路线、时间节点等详细信息。
 *
 * @requirement(name="多方案对比分析", id="SRS-TMS-04")
 * 支持最多5个方案的关键指标并列比较。
 *
 * @requirement(name="方案重构操作", id="SRS-TMS-06")
 * 基于新约束条件重新生成或调整现有方案。
 *
 * @requirement(name="方案分发驱动", id="SRS-TMS-08")
 * 将选定方案解析为指令集，下发至指定执行节点。
 *
 * @requirement(name="执行状态监控", id="SRS-TMS-10")
 * 实时聚合子任务进度，展示整体完成率与当前状态。
 */
@Service
public class SchemeService {

    private static final Logger log = LoggerFactory.getLogger(SchemeService.class);

    private final SchemeRepository schemeRepository;

    public SchemeService(SchemeRepository schemeRepository) {
        this.schemeRepository = schemeRepository;
    }

    /**
     * 查询任务方案列表，支持排序和分页。
     *
     * @param sortField     排序字段（createTime / priority / successRate / estimatedDuration / estimatedLossRatio）
     * @param sortDirection 排序方向（asc / desc）
     * @param page          页码
     * @param size          每页条数
     * @return 方案列表
     */
    public List<TaskScheme> listSchemes(String sortField, String sortDirection, int page, int size) {
        List<TaskScheme> schemes = new ArrayList<>(schemeRepository.findAll());

        // 排序
        if (sortField != null && !sortField.isEmpty()) {
            Comparator<TaskScheme> comparator = getComparator(sortField);
            if (comparator != null) {
                if ("desc".equalsIgnoreCase(sortDirection)) {
                    schemes.sort(comparator.reversed());
                } else {
                    schemes.sort(comparator);
                }
            }
        }

        // 分页
        int fromIndex = Math.max(0, page * size);
        if (fromIndex >= schemes.size()) {
            return new ArrayList<>();
        }
        int toIndex = Math.min(fromIndex + size, schemes.size());
        return schemes.subList(fromIndex, toIndex);
    }

    /**
     * 获取排序比较器。
     */
    private Comparator<TaskScheme> getComparator(String sortField) {
        return switch (sortField) {
            case "createTime" -> Comparator.comparing(TaskScheme::getCreateTime, Comparator.nullsLast(Comparator.naturalOrder()));
            case "priority" -> Comparator.comparingInt(TaskScheme::getPriority);
            case "successRate" -> Comparator.comparingDouble(TaskScheme::getSuccessRate);
            case "estimatedDuration" -> Comparator.comparingInt(TaskScheme::getEstimatedDuration);
            case "estimatedLossRatio" -> Comparator.comparingDouble(TaskScheme::getEstimatedLossRatio);
            default -> Comparator.comparing(TaskScheme::getCreateTime, Comparator.nullsLast(Comparator.naturalOrder()));
        };
    }

    /**
     * 查询方案详情。
     *
     * @param schemeId 方案ID
     * @return 方案
     */
    public Optional<TaskScheme> getSchemeDetail(String schemeId) {
        return schemeRepository.findById(schemeId);
    }

    /**
     * 多方案对比分析。
     * <p>
     * 最多支持5个方案的关键指标并列比较。
     * </p>
     *
     * @param compareDTO 对比参数
     * @return 对比结果Map
     */
    public Map<String, Object> compareSchemes(SchemeCompareDTO compareDTO) {
        List<String> schemeIds = compareDTO.getSchemeIds();
        if (schemeIds == null || schemeIds.isEmpty()) {
            throw new IllegalArgumentException("至少需要一个方案进行对比");
        }
        if (schemeIds.size() > 5) {
            throw new IllegalArgumentException("最多支持5个方案对比");
        }

        List<String> compareFields = compareDTO.getCompareFields();
        if (compareFields == null || compareFields.isEmpty()) {
            compareFields = Arrays.asList("estimatedDuration", "estimatedLossRatio", "successRate", "priority");
        }

        Map<String, Object> result = new LinkedHashMap<>();
        result.put("compareFields", compareFields);

        List<Map<String, Object>> schemeComparisons = new ArrayList<>();
        for (String schemeId : schemeIds) {
            Optional<TaskScheme> schemeOpt = schemeRepository.findById(schemeId);
            if (schemeOpt.isPresent()) {
                TaskScheme scheme = schemeOpt.get();
                Map<String, Object> schemeData = new LinkedHashMap<>();
                schemeData.put("schemeId", scheme.getSchemeId());
                schemeData.put("schemeName", scheme.getSchemeName());
                schemeData.put("schemeType", scheme.getSchemeType());
                schemeData.put("status", scheme.getStatus());

                for (String field : compareFields) {
                    Object value = getFieldValue(scheme, field);
                    schemeData.put(field, value);
                }
                schemeComparisons.add(schemeData);
            }
        }
        result.put("schemes", schemeComparisons);
        return result;
    }

    /**
     * 获取方案字段值。
     */
    private Object getFieldValue(TaskScheme scheme, String field) {
        return switch (field) {
            case "estimatedDuration" -> scheme.getEstimatedDuration();
            case "estimatedLossRatio" -> scheme.getEstimatedLossRatio();
            case "successRate" -> scheme.getSuccessRate();
            case "priority" -> scheme.getPriority();
            case "executionProgress" -> scheme.getExecutionProgress();
            case "version" -> scheme.getVersion();
            default -> null;
        };
    }

    /**
     * 方案重构。
     * <p>
     * 基于新约束条件重新生成方案，保留与旧版本的关联。
     * </p>
     *
     * @param schemeId       原方案ID
     * @param newConstraints 新约束条件（JSON格式）
     * @return 重构后的新方案
     */
    public TaskScheme reconstructScheme(String schemeId, String newConstraints) {
        TaskScheme original = schemeRepository.findById(schemeId)
                .orElseThrow(() -> new IllegalArgumentException("方案不存在: " + schemeId));

        log.info("开始重构方案 {}，新约束: {}", schemeId, newConstraints);

        // 创建新方案（基于原方案调整）
        TaskScheme newScheme = new TaskScheme();
        newScheme.setSchemeName(original.getSchemeName() + " (重构版)");
        newScheme.setSchemeType(original.getSchemeType());
        newScheme.setEventId(original.getEventId());
        newScheme.setDraftId(original.getDraftId());
        newScheme.setStatus(SchemeStatus.PENDING_DISPATCH);
        newScheme.setPriority(original.getPriority());
        newScheme.setEstimatedDuration(original.getEstimatedDuration());
        newScheme.setEstimatedLossRatio(original.getEstimatedLossRatio());
        newScheme.setSuccessRate(original.getSuccessRate());
        newScheme.setDeploymentDetail(original.getDeploymentDetail());
        newScheme.setRouteDetail(original.getRouteDetail());
        newScheme.setTimelineDetail(original.getTimelineDetail());
        newScheme.setAlgorithmTrace("基于原方案 " + schemeId + " 重构，新约束: " + newConstraints);
        newScheme.setParentSchemeId(schemeId);
        newScheme.setVersion(original.getVersion() + 1);
        newScheme.setExecutionProgress(0);
        newScheme.setCreateTime(LocalDateTime.now());
        newScheme.setUpdateTime(LocalDateTime.now());

        TaskScheme saved = schemeRepository.save(newScheme);
        log.info("方案重构完成，新方案ID: {}", saved.getSchemeId());
        return saved;
    }

    /**
     * 方案分发。
     * <p>
     * 将选定方案解析为指令集并下发至指定执行节点。
     * </p>
     *
     * @param schemeId   方案ID
     * @param targetNode 目标执行节点
     * @return 分发结果
     */
    public Map<String, Object> dispatchScheme(String schemeId, String targetNode) {
        TaskScheme scheme = schemeRepository.findById(schemeId)
                .orElseThrow(() -> new IllegalArgumentException("方案不存在: " + schemeId));

        log.info("分发方案 {} 至执行节点: {}", schemeId, targetNode);

        // 更新方案状态为"分发中"
        schemeRepository.updateStatus(schemeId, SchemeStatus.DISPATCHING);

        // 构建分发指令集
        Map<String, Object> dispatchResult = new LinkedHashMap<>();
        dispatchResult.put("schemeId", schemeId);
        dispatchResult.put("schemeName", scheme.getSchemeName());
        dispatchResult.put("targetNode", targetNode);
        dispatchResult.put("dispatchTime", LocalDateTime.now().toString());
        dispatchResult.put("status", "已下发");
        dispatchResult.put("instructions", buildInstructions(scheme));

        // 模拟下发成功，更新状态为"执行中"
        schemeRepository.updateStatus(schemeId, SchemeStatus.EXECUTING);
        log.info("方案 {} 已成功分发给节点 {}", schemeId, targetNode);

        return dispatchResult;
    }

    /**
     * 构建指令集。
     */
    private List<Map<String, String>> buildInstructions(TaskScheme scheme) {
        List<Map<String, String>> instructions = new ArrayList<>();

        Map<String, String> cmd1 = new LinkedHashMap<>();
        cmd1.put("command", "DEPLOY");
        cmd1.put("target", scheme.getDeploymentDetail() != null ? "兵力部署" : "未知");
        cmd1.put("detail", scheme.getDeploymentDetail() != null ? scheme.getDeploymentDetail() : "{}");
        instructions.add(cmd1);

        Map<String, String> cmd2 = new LinkedHashMap<>();
        cmd2.put("command", "MOVE");
        cmd2.put("target", "行动路线");
        cmd2.put("detail", scheme.getRouteDetail() != null ? scheme.getRouteDetail() : "[]");
        instructions.add(cmd2);

        Map<String, String> cmd3 = new LinkedHashMap<>();
        cmd3.put("command", "TIMELINE");
        cmd3.put("target", "时间节点");
        cmd3.put("detail", scheme.getTimelineDetail() != null ? scheme.getTimelineDetail() : "{}");
        instructions.add(cmd3);

        return instructions;
    }

    /**
     * 查询方案执行状态。
     *
     * @param schemeId 方案ID
     * @return 执行状态信息
     */
    public Map<String, Object> getExecutionStatus(String schemeId) {
        TaskScheme scheme = schemeRepository.findById(schemeId)
                .orElseThrow(() -> new IllegalArgumentException("方案不存在: " + schemeId));

        Map<String, Object> status = new LinkedHashMap<>();
        status.put("schemeId", scheme.getSchemeId());
        status.put("schemeName", scheme.getSchemeName());
        status.put("status", scheme.getStatus());
        status.put("executionProgress", scheme.getExecutionProgress());
        status.put("subTaskStatus", scheme.getSubTaskStatus());
        status.put("updateTime", scheme.getUpdateTime());
        return status;
    }
}
