package com.zcloud.safetyDutyList.command.tasklist;

import com.zcloud.safetyDutyList.domain.enums.TaskStatusEnum;
import com.zcloud.safetyDutyList.domain.gateway.tasklist.FeedbackExceptionGateway;
import com.zcloud.safetyDutyList.domain.gateway.tasklist.FeedbackGateway;
import com.zcloud.safetyDutyList.domain.gateway.tasklist.TaskDetailGateway;
import com.zcloud.safetyDutyList.domain.gateway.tasklist.TaskExecutionGateway;
import com.zcloud.safetyDutyList.domain.gateway.tasklist.TaskListIssueGateway;
import com.zcloud.safetyDutyList.domain.model.tasklist.FeedbackE;
import com.zcloud.safetyDutyList.domain.model.tasklist.FeedbackExceptionE;
import com.zcloud.safetyDutyList.domain.model.tasklist.TaskDetailE;
import com.zcloud.safetyDutyList.domain.model.tasklist.TaskExecutionE;
import com.zcloud.safetyDutyList.domain.model.tasklist.TaskListIssueE;
import com.zcloud.safetyDutyList.domain.util.FeedbackCycleUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 定时任务2：反馈异常检测
 * <p>
 * 执行周期：每月1日0时
 * <p>
 * 实现逻辑：
 *   1. 获取所有 task_status=1 的任务执行记录，获取其反馈周期类型 feedback_cycle_type
 *   2. 根据反馈周期类型判断上一阶段是否有反馈记录，无记录则判定为异常
 *   判定规则：
 *     feedback_cycle_type=1（每月）：每个月都需要反馈至少一次
 *     feedback_cycle_type=2（每季度）：每个季度（自然月划分）都需要反馈至少一次
 *     feedback_cycle_type=3（每半年）：每半年（以自然月6月划分）都需要反馈至少一次
 *     feedback_cycle_type=4（年）：一年内必须反馈至少一次
 */
@Slf4j
@Component
@AllArgsConstructor
public class FeedbackExceptionCheckExe {
    private final TaskListIssueGateway taskListIssueGateway;
    private final TaskExecutionGateway taskExecutionGateway;
    private final TaskDetailGateway taskDetailGateway;
    private final FeedbackGateway feedbackGateway;
    private final FeedbackExceptionGateway feedbackExceptionGateway;

    @Scheduled(cron = "0 0 0 1 * ?")
    @Transactional(rollbackFor = Exception.class)
    public void execute() {
        log.info("【定时任务2】开始反馈异常检测...");
        List<TaskListIssueE> issuedList = taskListIssueGateway.listIssuedWithPeriod();
        if (issuedList == null || issuedList.isEmpty()) {
            log.info("【定时任务2】无需要检测的下发记录");
            return;
        }

        for (TaskListIssueE issueE : issuedList) {
            List<TaskExecutionE> executionList = taskExecutionGateway.listByTaskIssueId(issueE.getTaskIssueId());
            if (executionList == null) continue;

            for (TaskExecutionE executionE : executionList) {

                // 不是进行中就返回
                if (!TaskStatusEnum.IN_PROGRESS.getCode().equals(executionE.getTaskStatus())) continue;


                // 获取任务详情
                TaskDetailE detailE = taskDetailGateway.getByTaskDetailId(executionE.getTaskDetailId());
                if (detailE == null || detailE.getFeedbackCycleType() == null) continue;

                // 反馈周期枚举： 1（每月） 2（每季度） 3（每半年） 4（年）
                Integer feedbackCycleType = detailE.getFeedbackCycleType();

                // 首周期判断：如果当前仍处于清单的首个反馈周期内，跳过检测
                if (FeedbackCycleUtil.isFirstCycle(feedbackCycleType, issueE.getPeriodStartTime())) {
                    log.info("【定时任务2】任务执行[{}]仍处于首周期内，跳过检测", executionE.getTaskExecutionId());
                    continue;
                }

                // 生成上一阶段周期标识
                String previousPeriodFlag = FeedbackCycleUtil.generatePreviousPeriodFlag(feedbackCycleType);
                if (previousPeriodFlag == null) continue;

                // 防重：检查上一阶段是否已存在异常记录
                List<FeedbackExceptionE> existingExceptions = feedbackExceptionGateway
                        .listByTaskExecutionIdAndPeriodFlag(executionE.getTaskExecutionId(), previousPeriodFlag);
                if (existingExceptions != null && !existingExceptions.isEmpty()) {
                    log.debug("【定时任务2】任务执行[{}]周期[{}]已存在异常记录，跳过",
                            executionE.getTaskExecutionId(), previousPeriodFlag);
                    continue;
                }

                // 检查上一阶段是否有反馈记录
                List<FeedbackE> feedbackList = feedbackGateway.listByTaskExecutionIdAndPeriodFlag(
                        executionE.getTaskExecutionId(), previousPeriodFlag);
                if (feedbackList == null || feedbackList.isEmpty()) {
                    // 标记任务执行记录为异常
                    executionE.setFeedbackStatus(2);
                    taskExecutionGateway.update(executionE);

                    // 创建异常记录
                    createExceptionRecord(executionE, detailE, issueE, previousPeriodFlag);
                    log.info("【定时任务2】任务执行[{}]上一周期[{}]未反馈，已标记异常",
                            executionE.getTaskExecutionId(), previousPeriodFlag);
                }
            }
        }
        log.info("【定时任务2】反馈异常检测完成");
    }

    private void createExceptionRecord(TaskExecutionE executionE, TaskDetailE detailE,
                                       TaskListIssueE issueE, String previousPeriodFlag) {

        // 根据上一阶段周期标识计算起止时间
        LocalDateTime[] periodTime = FeedbackCycleUtil.getPeriodTime(previousPeriodFlag);

        FeedbackExceptionE exceptionE = new FeedbackExceptionE();
        exceptionE.init();
        exceptionE.setTaskDetailId(executionE.getTaskDetailId());
        exceptionE.setTaskExecutionId(executionE.getTaskExecutionId());
        exceptionE.setTaskListId(executionE.getTaskListId());
        exceptionE.setTaskIssueId(executionE.getTaskIssueId());
        exceptionE.setExceptionPeriodFlag(previousPeriodFlag);
        exceptionE.setExceptionPeriodStartTime(periodTime != null ? periodTime[0] : null);
        exceptionE.setExceptionPeriodEndTime(periodTime != null ? periodTime[1] : null);
        exceptionE.setExceptionType(1);
        exceptionE.setExceptionTime(LocalDateTime.now());
        feedbackExceptionGateway.add(exceptionE);
    }
}
