package com.inspect.taskstatus.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.inspect.annotation.TaskStatusChange;
import com.inspect.base.core.constant.Color;
import com.inspect.base.core.constant.RedisConst;
import com.inspect.base.core.enums.TaskStatus;
import com.inspect.base.core.enums.TaskType;
import com.inspect.base.core.utils.BigDecimalUtil;
import com.inspect.base.core.utils.DateUtils;
import com.inspect.base.core.utils.StringUtils;
import com.inspect.base.redis.service.RedisService;
import com.inspect.partrolresult.mapper.PatrolResultMapper;
import com.inspect.partrolresult.service.IPatrolResultService;
import com.inspect.resultmain.domain.PatrolTaskResultMain;
import com.inspect.resultmain.service.IPatrolTaskResultMainService;
import com.inspect.task.domain.PatrolTask;
import com.inspect.task.service.IPatrolTaskService;
import com.inspect.taskstatus.domain.PatrolTaskStatus;
import com.inspect.taskstatus.domain.TaskCount;
import com.inspect.taskstatus.mapper.PatrolTaskStatusMapper;
import com.inspect.taskstatus.service.IPatrolTaskStatusService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

@Service
public class PatrolTaskStatusServiceImpl implements IPatrolTaskStatusService {
    private final Logger log = LoggerFactory.getLogger(this.getClass());
    private final PatrolTaskStatusMapper patrolTaskStatusMapper;

    @Resource
    private RedisService redisService;

    @Resource
    private IPatrolTaskService patrolTaskService;

    @Resource
    private IPatrolTaskResultMainService patrolTaskResultMainService;

    @Resource
    private IPatrolResultService patrolResultService;

    @Autowired
    public PatrolTaskStatusServiceImpl(PatrolTaskStatusMapper patrolTaskStatusMapper) {
        this.patrolTaskStatusMapper = patrolTaskStatusMapper;
    }

    public PatrolTaskStatus selectPatrolTaskStatusByLineId(Long lineId) {
        return this.patrolTaskStatusMapper.selectPatrolTaskStatusByLineId(lineId);
    }

    public PatrolTaskStatus selectPatrolTaskStatusByTaskPatrolledId(String taskPatrolledId) {
        return this.patrolTaskStatusMapper.selectPatrolTaskStatusByTaskPatrolledId(taskPatrolledId);
    }

    public List<PatrolTaskStatus> selectPatrolTaskStatusList(PatrolTaskStatus patrolTaskStatus) {
        return this.patrolTaskStatusMapper.selectPatrolTaskStatusList(patrolTaskStatus);
    }

    public List<PatrolTaskStatus> selectPatrolTaskStatusCount(PatrolTaskStatus patrolTaskStatus) {
        return this.patrolTaskStatusMapper.selectPatrolTaskStatusCount(patrolTaskStatus);
    }

    public List<TaskCount> selectCountList(PatrolTaskStatus patrolTaskStatus) {
        return this.patrolTaskStatusMapper.selectCountList(patrolTaskStatus);
    }

    @Override
    public List<TaskCount> selectCountListByDate(PatrolTaskStatus patrolTaskStatus) {
        return this.patrolTaskStatusMapper.selectCountListByDate(patrolTaskStatus);
    }

    @TaskStatusChange(targetState = "1", async = true) // "1"表示已完成状态
    public int insertPatrolTaskStatus(PatrolTaskStatus patrolTaskStatus) {
        patrolTaskStatus.setCreateTime(new Date());
        patrolTaskStatus.setStartTime(new Date());
        return this.patrolTaskStatusMapper.insertPatrolTaskStatus(patrolTaskStatus);
    }

    @Override
    @TaskStatusChange(targetState = "1", async = true) // "1"表示已完成状态
    public int updatePatrolTaskStatus(PatrolTaskStatus patrolTaskStatus) {
        log.info(Color.RED + "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" + Color.END);
        log.info("patrolTaskStatus: {}", patrolTaskStatus);
        return this.patrolTaskStatusMapper.updatePatrolTaskStatus(patrolTaskStatus);
    }

    public int updatePatrolTaskStatusOfTaskProgress(PatrolTaskStatus patrolTaskStatus) {
        return this.patrolTaskStatusMapper.updatePatrolTaskStatusOfTaskProgress(patrolTaskStatus);
    }

    @TaskStatusChange(targetState = "1", async = true) // "1"表示已完成状态
    public int updatePatrolTaskStatusOfTaskState(PatrolTaskStatus patrolTaskStatus) {
        return this.patrolTaskStatusMapper.updatePatrolTaskStatusOfTaskState(patrolTaskStatus);
    }

    public int updatePatrolTaskStatusOfTaskStateAndEndTime(PatrolTaskStatus patrolTaskStatus) {
        return this.patrolTaskStatusMapper.updatePatrolTaskStatusOfTaskStateAndEndTime(patrolTaskStatus);
    }

    public int updatePatrolTaskStatusRunning(PatrolTaskStatus patrolTaskStatus) {
        return this.patrolTaskStatusMapper.updatePatrolTaskStatusRunning(patrolTaskStatus);
    }

    public int deletePatrolTaskStatusByLineIds(Long[] lineIds) {
        return this.patrolTaskStatusMapper.deletePatrolTaskStatusByLineIds(lineIds);
    }

    public int deletePatrolTaskStatusByLineId(Long lineId) {
        return this.patrolTaskStatusMapper.deletePatrolTaskStatusByLineId(lineId);
    }

    @Override
    public int insertIgnorePatrolTaskStatus(PatrolTaskStatus patrolTaskStatusMain) {
        return this.patrolTaskStatusMapper.insertIgnorePatrolTaskStatus(patrolTaskStatusMain);
    }

    @Override
    public List<PatrolTaskStatus> selectPatrolTaskStatusListByMainId(String taskPatrolledId) {
        return this.patrolTaskStatusMapper.selectPatrolTaskStatusListByMainId(taskPatrolledId);
    }

    @Override
    public PatrolTaskStatus selectPatrolTaskStatusMain(String taskPatrolledId) {
        return patrolTaskStatusMapper.selectPatrolTaskStatusMain(taskPatrolledId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTaskProgress(Long lineId, String collectionProgress, String algorithmProgress, String state) {
        log.info("==========updateTaskProgress=============== lineId: {}", lineId);
        if (lineId == null) {
            throw new IllegalArgumentException("lineId 不能为空");
        }

        // 查找任务
        PatrolTaskStatus patrolTaskStatus = selectPatrolTaskStatusByLineId(lineId);

        if (patrolTaskStatus == null) {
            throw new IllegalArgumentException("执行任务不存在，lineId: " + lineId);
        }

        // 主任务由子任务更新
        if (TaskType.MAIN.getCode().equals(patrolTaskStatus.getTaskType())) {
            throw new IllegalArgumentException("主任务进度/状态由子任务自动计算，不能直接修改：" + patrolTaskStatus.getTaskPatrolledId());
        }

        patrolTaskStatus.setTaskProgress(collectionProgress);
        patrolTaskStatus.setTaskEstimatedTime(algorithmProgress);
        patrolTaskStatus.setTaskState(state);
        setNormalTaskStatus(patrolTaskStatus);

        // 更新子任务或普通任务
        updatePatrolTaskStatus(patrolTaskStatus);
        log.info("updateTaskProgress: {}", patrolTaskStatus);
        // 如果是子任务，需要同步更新主任务
        if (TaskType.SUB.getCode().equals(patrolTaskStatus.getTaskType()) && patrolTaskStatus.getMainId() != null) {
            updateMainTask(patrolTaskStatus.getMainId(), patrolTaskStatus.getTaskCode());
        }
    }

    private void updateMainTask(String mainId, String taskCode) {
        // 查找子任务
        List<PatrolTaskStatus> subTasks = selectPatrolTaskStatusListByMainId(mainId);
        if (subTasks.isEmpty()) {
            return;
        }

        PatrolTaskStatus mainTask = selectPatrolTaskStatusByTaskPatrolledId(mainId);

        BigDecimal execTotalPoints = BigDecimal.ZERO;
        BigDecimal execTotalAlgorithms = BigDecimal.ZERO;
        TaskStatus mainTaskState = TaskStatus.DONE;

        // 计算平均进度
        for (PatrolTaskStatus subTask : subTasks) {
            String[] taskNames = subTask.getTaskName().split("@");
            log.info("taskNames: {}", subTask.getTaskName());
            if (taskNames.length > 1) {
                String sendCode = taskNames[0];
                // 指定任务算法
                List<String> algList = patrolResultService.selectAlgList(taskCode, sendCode, mainTask.getSpecifiedAlg());
                int subTotalPoints = algList.size();
                int subTotalAlgorithms = algList.stream().mapToInt(s -> s.split(",").length).sum();

                BigDecimal subTaskProgress = BigDecimalUtil.toBigDecimal(subTask.getTaskProgress());
                BigDecimal subAlgorithmProgress = BigDecimalUtil.toBigDecimal(subTask.getTaskEstimatedTime());
                BigDecimal subExecPoints = subTaskProgress.multiply(new BigDecimal(subTotalPoints)).divide(BigDecimal.valueOf(100), 1, RoundingMode.DOWN);
                BigDecimal subExecAlgorithms = subAlgorithmProgress.multiply(new BigDecimal(subTotalAlgorithms)).divide(BigDecimal.valueOf(100), 1, RoundingMode.DOWN);
                execTotalPoints = execTotalPoints.add(subExecPoints);
                execTotalAlgorithms = execTotalAlgorithms.add(subExecAlgorithms);
                log.info("subTotalPoints:{},subTotalAlgorithms:{},execTotalPoints:{},execTotalAlgorithms:{}", subTotalPoints, subTotalAlgorithms, execTotalPoints, execTotalAlgorithms);
            }

            // 按状态优先级设置主任务状态
            TaskStatus subTaskState = TaskStatus.fromCode(subTask.getTaskState());
            if (subTaskState == null) {
                continue;
            }
            if (mainTaskState.getPriority() > subTaskState.getPriority()) {
                mainTaskState = subTaskState;
            }
        }

        List<String> algList = patrolResultService.selectAlgList(taskCode, null, mainTask.getSpecifiedAlg());
        int totalPoints = algList.size();
        int totalAlgorithms = algList.stream().mapToInt(s -> s.split(",").length).sum();
        log.info("totalPoints:{},totalAlgorithms:{}", totalPoints, totalAlgorithms);
        BigDecimal mainTaskProgress = execTotalPoints
                .multiply(BigDecimal.valueOf(100))
                .divide(
                        BigDecimal.valueOf(totalPoints),
                        1, RoundingMode.DOWN
                );

        BigDecimal mainAlgorithmProgress = execTotalAlgorithms
                .multiply(BigDecimal.valueOf(100))
                .divide(
                        BigDecimal.valueOf(totalAlgorithms),
                        1, RoundingMode.DOWN
                );

        // 如果状态为已完成，但采集和分析进度小于100，说明还有任务未上报，更新为运行中
        if (mainTaskState.getCode().equals(TaskStatus.DONE.getCode())
                && (mainTaskProgress.compareTo(new BigDecimal(100)) != 0 || mainAlgorithmProgress.compareTo(new BigDecimal(100)) != 0)) {
            mainTaskState = TaskStatus.RUNNING;
        }

        mainTask.setTaskState(mainTaskState.getCode());
        mainTask.setTaskProgress(mainTaskProgress.toString());
        mainTask.setTaskEstimatedTime(mainAlgorithmProgress.toString());
        setNormalTaskStatus(mainTask);

        // 更新主任务
        patrolTaskStatusMapper.updatePatrolTaskStatus(mainTask);
    }

    // 生成巡视归档记录
    @Override
    public int generateTaskResultMain(PatrolTaskStatus patrolTaskStatus) {
        int mainId = -1;
        if (patrolTaskStatus != null && !patrolTaskStatus.getTaskType().equals(TaskType.SUB.getCode())) {
            PatrolTaskResultMain taskResultMain = new PatrolTaskResultMain();
            taskResultMain.setTaskId(patrolTaskStatus.getTaskCode());
            taskResultMain.setTaskCode(patrolTaskStatus.getTaskCode());
            taskResultMain.setTaskTime(patrolTaskStatus.getStartTime());
            taskResultMain.setTaskPatrolledId(patrolTaskStatus.getTaskPatrolledId());
            taskResultMain.setTaskName(patrolTaskStatus.getTaskName());
            taskResultMain.setCreateBy("sys");
            taskResultMain.setCreateTime(new Date());
            taskResultMain.setFileStatus("0");
            PatrolTask patrolTask = patrolTaskService.selectPatrolTaskByTaskId(Long.valueOf(patrolTaskStatus.getTaskCode()));
            taskResultMain.setTaskType(patrolTask.getType());
            taskResultMain.setDevType(patrolTask.getDevType());
            if (patrolTask != null && StringUtils.isNotEmpty(patrolTask.getAreaName())) {
                taskResultMain.setAreaName(patrolTask.getAreaName());
            }

            taskResultMain.setUnifiedTaskPatrolledId(patrolTaskStatus.getTaskPatrolledId());

            mainId = patrolTaskResultMainService.insertPatrolTaskResultMain(taskResultMain);
            log.info("生成巡视归档记录: {}", taskResultMain);
        } else {
            log.info("子任务不生成归档记录！");
        }

        return mainId;
    }

    private String getTaskPointsSummary(String taskCode, String taskPatrolledId, String specifiedAlg) {
        // 任务总点位和算法
        List<Map<String, String>> totalPointList = patrolTaskStatusMapper.selectTotalPointsAndAlgs(taskCode);

        // 任务指定算法类型
        if (StringUtils.isNotEmpty(specifiedAlg)) {
            Map<String, String> algorithmInfo = patrolResultService.selectAlgorithmInfo(specifiedAlg);
            totalPointList.stream().forEach(item -> item.put("alg_subtype_ids", String.valueOf(algorithmInfo.get("alg_subtype_id"))));
        }
        // 任务已巡检点位和算法
        List<Map<String, String>> executedPointList = patrolTaskStatusMapper.selectExecutedPointsAndAlgs(taskPatrolledId);
        return countInspectedPoint(totalPointList, executedPointList);
    }

    /**
     * 统计点位巡检情况
     *
     * @param data1List 总点位和算法
     * @param data2List 已执行点位和算法
     * @return
     */
    private String countInspectedPoint(List<Map<String, String>> data1List, List<Map<String, String>> data2List) {
        Map<String, Set<String>> data2Map = new HashMap<>();
        for (Map<String, String> row : data2List) {
            String pid = String.valueOf(row.get("patrol_point_id"));
            String subtype = String.valueOf(row.get("alg_subtype_id"));

            data2Map.computeIfAbsent(pid, k -> new HashSet<>()).add(subtype);
        }

        // 遍历 data1，检查每个 patrol_point_id 是否全部子类型都存在
        int count = 0;
        for (Map<String, String> row : data1List) {
            String pid = String.valueOf(row.get("patrol_point_id"));
            String idsStr = String.valueOf(row.get("alg_subtype_ids"));

            if (idsStr == null || idsStr.trim().isEmpty()) {
                continue; // 空则跳过
            }

            // 解析逗号分隔的 alg_subtype_ids
            Set<String> requiredSet = new HashSet<>();
            for (String s : idsStr.split(",")) {
                String trim = s.trim();
                if (!trim.isEmpty()) {
                    requiredSet.add(trim);
                }
            }

            // 判断是否是 data2 的子集
            Set<String> availableSet = data2Map.get(pid);
            if (availableSet != null && availableSet.containsAll(requiredSet)) {
                count++;
            }
        }

        JSONObject result = new JSONObject();
        result.put("totalPoint", data1List.size());
        result.put("executedPoint", count);
        result.put("unexecutedPoint", (data1List.size() - count));

        return result.toJSONString();
    }

    private void setNormalTaskStatus(PatrolTaskStatus patrolTaskStatus) {
        // 任务最终状态：已完成、已终止
        boolean isFinalState = TaskStatus.DONE.getCode().equals(patrolTaskStatus.getTaskState()) || TaskStatus.HALTED.getCode().equals(patrolTaskStatus.getTaskState());
        // 常规任务：主任务、普通任务
        boolean isNormalTask = TaskType.ORDINARY.getCode().equals(patrolTaskStatus.getTaskType()) || TaskType.MAIN.getCode().equals(patrolTaskStatus.getTaskType());

        // 更新任务结束时间和redis任务执行标识
        if (isFinalState) {
            String endTime = DateUtils.parseDateToStr(DateUtils.yyyyMMddHHmmss2, new Date());
            patrolTaskStatus.setEndTime(endTime);

            if (isNormalTask) {
                redisService.deleteObjectOfTask(RedisConst.TASK_CURRENT_CODE, patrolTaskStatus.getTaskCode());
            }
        }

        // 更新的点位汇总信息
        if (isNormalTask) {
            String summary = getTaskPointsSummary(patrolTaskStatus.getTaskCode(), patrolTaskStatus.getTaskPatrolledId(), patrolTaskStatus.getSpecifiedAlg());
            patrolTaskStatus.setSummary(summary);
        }
    }
}
