package com.sundot.airport.exam.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.sundot.airport.exam.domain.DailyAnswerRecord;
import com.sundot.airport.exam.domain.DailyTask;
import com.sundot.airport.exam.domain.DailyTaskDetail;
import com.sundot.airport.exam.dto.NotifyTaskDTO;
import com.sundot.airport.exam.enums.DailyTaskStatusEnum;
import com.sundot.airport.exam.mapper.DailyAnswerRecordMapper;
import com.sundot.airport.exam.mapper.DailyTaskDetailMapper;
import com.sundot.airport.exam.mapper.DailyTaskMapper;
import com.sundot.airport.exam.service.IDailyTaskExpireService;
import com.sundot.airport.exam.util.BusinessDateUtil;
import com.sundot.airport.system.domain.SysNotice;
import com.sundot.airport.system.service.ISysNoticeService;
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 java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

/**
 * <b>功能名：</b>DailyTaskExpireServiceImpl<br>
 * <b>说明：</b> 每日任务逾期处理Service实现 <br>
 * <b>著作权：</b> Copyright (C) 2025 SUNDOT CORPORATION<br>
 * <b>修改履历：
 *
 * @author Simon Lin
 */
@Service
public class DailyTaskExpireServiceImpl implements IDailyTaskExpireService {

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

    @Autowired
    private DailyTaskMapper dailyTaskMapper;

    @Autowired
    private DailyTaskDetailMapper dailyTaskDetailMapper;

    @Autowired
    private DailyAnswerRecordMapper dailyAnswerRecordMapper;

    @Autowired
    private ISysNoticeService sysNoticeService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int processExpiredTasks() {
        log.info("开始处理逾期任务");

        // 1. 获取当前业务日期
        LocalDate currentBusinessDate = BusinessDateUtil.getCurrentBusinessDate();
        LocalDateTime now = LocalDateTime.now();

        log.info("当前业务日期: {}, 当前时间: {}", currentBusinessDate, now);

        // 2. 查询所有待答题和答题中的任务
        LambdaQueryWrapper<DailyTask> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(DailyTask::getDtStatus,
                DailyTaskStatusEnum.PENDING.getCode(),
                DailyTaskStatusEnum.IN_PROGRESS.getCode());
        wrapper.eq(DailyTask::getDelStatus, 0);

        List<DailyTask> pendingTasks = dailyTaskMapper.selectList(wrapper);

        if (pendingTasks.isEmpty()) {
            log.info("没有待处理的任务");
            return 0;
        }

        log.info("查询到 {} 个待答题/答题中的任务", pendingTasks.size());

        int expiredCount = 0;

        // 3. 遍历任务，判断是否逾期
        for (DailyTask task : pendingTasks) {
            // Convert Date to LocalDate
            Date businessDate = task.getDtBusinessDate();
            if (businessDate == null) {
                continue;
            }
            LocalDate taskBusinessDate = businessDate.toInstant()
                    .atZone(java.time.ZoneId.systemDefault())
                    .toLocalDate();

            // 判断任务的业务日期是否已经结束
            // 业务日期结束时间：5天后的7:00（任务过期时间为5天）
            LocalDateTime businessDateEnd = BusinessDateUtil.getBusinessDateStart(taskBusinessDate.plusDays(5));

            // 如果当前时间已经超过业务日期结束时间，则任务逾期
            if (now.isAfter(businessDateEnd)) {
                // 1. 更新任务状态为已逾期
                task.setDtStatus(DailyTaskStatusEnum.EXPIRED.getCode());
                task.setDtTotalScore(BigDecimal.ZERO);
                task.setUpdateTime(new Date());
                task.setUpdateUid("SYSTEM");
                dailyTaskMapper.updateById(task);

                // 2. 更新任务明细状态：将所有未答题的题目标记为超时未答
                LambdaUpdateWrapper<DailyTaskDetail> detailUpdateWrapper = new LambdaUpdateWrapper<>();
                detailUpdateWrapper.eq(DailyTaskDetail::getDtdTaskId, task.getDtId())
                        .eq(DailyTaskDetail::getDtdAnswerStatus, "PENDING")  // 只更新待答题状态的题目
                        .set(DailyTaskDetail::getDtdAnswerStatus, "TIMEOUT")
                        .set(DailyTaskDetail::getDtdIsCorrect, false)
                        .set(DailyTaskDetail::getDtdActualScore, BigDecimal.ZERO)
                        .set(DailyTaskDetail::getDtdAnswerTime, new Date())
                        .set(DailyTaskDetail::getUpdateTime, new Date())
                        .set(DailyTaskDetail::getUpdateUid, "SYSTEM");

                int updatedDetailCount = dailyTaskDetailMapper.update(null, detailUpdateWrapper);

                log.info("更新任务明细超时状态 - taskId: {}, 更新{}个题目", task.getDtId(), updatedDetailCount);

                // 3. 查询该任务的所有明细，统计答题情况
                LambdaQueryWrapper<DailyTaskDetail> detailQueryWrapper = new LambdaQueryWrapper<>();
                detailQueryWrapper.eq(DailyTaskDetail::getDtdTaskId, task.getDtId());
                List<DailyTaskDetail> allDetails = dailyTaskDetailMapper.selectList(detailQueryWrapper);

                int correctCount = 0;
                int wrongCount = 0;
                int timeoutCount = 0;
                BigDecimal totalScore = BigDecimal.ZERO;
                BigDecimal actualScore = BigDecimal.ZERO;

                for (DailyTaskDetail detail : allDetails) {
                    totalScore = totalScore.add(detail.getDtdScore());

                    if ("ANSWERED".equals(detail.getDtdAnswerStatus())) {
                        if (Boolean.TRUE.equals(detail.getDtdIsCorrect())) {
                            correctCount++;
                            actualScore = actualScore.add(detail.getDtdActualScore() != null ? detail.getDtdActualScore() : BigDecimal.ZERO);
                        } else {
                            wrongCount++;
                        }
                    } else if ("TIMEOUT".equals(detail.getDtdAnswerStatus())) {
                        timeoutCount++;
                    }
                }

                BigDecimal correctRate = allDetails.size() > 0
                    ? BigDecimal.valueOf(correctCount * 100.0 / allDetails.size()).setScale(2, BigDecimal.ROUND_HALF_UP)
                    : BigDecimal.ZERO;

                // 4. 创建或更新答题记录
                LambdaQueryWrapper<DailyAnswerRecord> recordQueryWrapper = new LambdaQueryWrapper<>();
                recordQueryWrapper.eq(DailyAnswerRecord::getDarTaskId, task.getDtId())
                        .eq(DailyAnswerRecord::getDarUserId, task.getDtUserId());
                DailyAnswerRecord existingRecord = dailyAnswerRecordMapper.selectOne(recordQueryWrapper);

                if (existingRecord != null) {
                    // 更新已有记录
                    existingRecord.setDarSubmitTime(new Date());
                    existingRecord.setDarSubmitType("AUTO_EXPIRED");  // 逾期自动提交
                    existingRecord.setDarTotalScore(totalScore);
                    existingRecord.setDarActualScore(actualScore);
                    existingRecord.setDarCorrectCount(correctCount);
                    existingRecord.setDarWrongCount(wrongCount);
                    existingRecord.setDarTimeoutCount(timeoutCount);
                    existingRecord.setDarCorrectRate(correctRate);
                    existingRecord.setUpdateTime(new Date());
                    existingRecord.setUpdateUid("SYSTEM");

                    // 计算答题用时（如果有开始时间）
                    if (existingRecord.getDarStartTime() != null) {
                        long timeUsed = (new Date().getTime() - existingRecord.getDarStartTime().getTime()) / 1000;
                        existingRecord.setDarTimeUsed((int) timeUsed);
                    }

                    dailyAnswerRecordMapper.updateById(existingRecord);
                    log.info("更新答题记录 - recordId: {}, actualScore: {}", existingRecord.getDarId(), actualScore);
                } else {
                    // 创建新记录（任务从未开始就逾期的情况）
                    DailyAnswerRecord newRecord = new DailyAnswerRecord();
                    newRecord.setDarId("DAR" + System.currentTimeMillis());  // 生成简单ID
                    newRecord.setDarUserId(task.getDtUserId());
                    newRecord.setDarTaskId(task.getDtId());
                    newRecord.setDarSetNo(1);
                    newRecord.setDarStartTime(null);  // 从未开始
                    newRecord.setDarSubmitTime(new Date());
                    newRecord.setDarSubmitType("AUTO_EXPIRED");
                    newRecord.setDarTimeUsed(0);
                    newRecord.setDarTotalScore(totalScore);
                    newRecord.setDarActualScore(BigDecimal.ZERO);  // 未答题，得分为0
                    newRecord.setDarCorrectCount(0);
                    newRecord.setDarWrongCount(0);
                    newRecord.setDarTimeoutCount(allDetails.size());
                    newRecord.setDarCorrectRate(BigDecimal.ZERO);
                    newRecord.setCreateTime(new Date());
                    newRecord.setCreateUid("SYSTEM");

                    dailyAnswerRecordMapper.insert(newRecord);
                    log.info("创建答题记录 - recordId: {}, 任务从未开始", newRecord.getDarId());
                }

                log.info("任务已逾期 - taskId: {}, userId: {}, businessDate: {}, correctCount: {}, wrongCount: {}, timeoutCount: {}",
                        task.getDtId(), task.getDtUserId(), taskBusinessDate, correctCount, wrongCount, timeoutCount);

                expiredCount++;
            }
        }

        log.info("逾期任务处理完成 - 共处理 {} 个任务", expiredCount);

        return expiredCount;
    }

    @Override
    public boolean notifyExpiredTask(NotifyTaskDTO dto) {
        try {
            log.info("开始提醒用户完成逾期任务 - taskId: {}, notifyType: {}", dto.getTaskId(), dto.getNotifyType());

            // 1. 查询任务信息（使用业务主键 dtId）
            LambdaQueryWrapper<DailyTask> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(DailyTask::getDtId, dto.getTaskId())
                   .eq(DailyTask::getDelStatus, 0);
            DailyTask task = dailyTaskMapper.selectOne(wrapper);

            if (task == null) {
                log.warn("任务不存在 - taskId: {}", dto.getTaskId());
                return false;
            }

            // 2. 检查任务是否逾期
            if (!DailyTaskStatusEnum.EXPIRED.getCode().equals(task.getDtStatus())) {
                log.warn("任务未逾期，无需提醒 - taskId: {}, status: {}", dto.getTaskId(), task.getDtStatus());
                return false;
            }

            // 3. 根据通知类型发送通知
            boolean result = false;
            switch (dto.getNotifyType().toUpperCase()) {
                case "MESSAGE":
                    result = sendSystemMessage(task, dto.getMessage());
                    break;
                case "EMAIL":
                    result = sendEmail(task, dto.getMessage());
                    break;
                case "SMS":
                    result = sendSMS(task, dto.getMessage());
                    break;
                default:
                    log.warn("不支持的通知类型: {}", dto.getNotifyType());
                    return false;
            }

            if (result) {
                log.info("提醒发送成功 - taskId: {}, userId: {}", task.getDtId(), task.getDtUserId());
            } else {
                log.warn("提醒发送失败 - taskId: {}, userId: {}", task.getDtId(), task.getDtUserId());
            }

            return result;
        } catch (Exception e) {
            log.error("提醒用户完成逾期任务失败 - taskId: " + dto.getTaskId(), e);
            return false;
        }
    }

    @Override
    public int batchNotifyExpiredTasks(NotifyTaskDTO dto) {
        try {
            log.info("开始批量提醒用户完成逾期任务 - taskIds: {}, notifyType: {}", dto.getTaskIds(), dto.getNotifyType());

            if (dto.getTaskIds() == null || dto.getTaskIds().isEmpty()) {
                log.warn("任务ID列表为空");
                return 0;
            }

            int successCount = 0;
            for (String taskId : dto.getTaskIds()) {
                NotifyTaskDTO singleDto = new NotifyTaskDTO();
                singleDto.setTaskId(taskId);
                singleDto.setNotifyType(dto.getNotifyType());
                singleDto.setMessage(dto.getMessage());

                if (notifyExpiredTask(singleDto)) {
                    successCount++;
                }
            }

            log.info("批量提醒完成 - 共提醒 {} 个任务", successCount);
            return successCount;
        } catch (Exception e) {
            log.error("批量提醒用户完成逾期任务失败", e);
            return 0;
        }
    }

    /**
     * 发送系统站内消息
     */
    private boolean sendSystemMessage(DailyTask task, String message) {
        try {
            SysNotice notice = new SysNotice();
            notice.setNoticeTitle("每日答题任务逾期提醒");
            notice.setNoticeType("1");  // 1-通知
            notice.setStatus("0");      // 0-正常

            // 构建通知内容
            StringBuilder content = new StringBuilder();
            content.append("尊敬的").append(task.getDtUserName()).append("：\n\n");

            if (message != null && !message.isEmpty()) {
                content.append(message);
            } else {
                content.append("您有逾期任务需要处理！\n");
                content.append("任务ID: ").append(task.getDtId()).append("\n");
                content.append("业务日期: ").append(task.getDtBusinessDate()).append("\n");
                content.append("过期时间: ").append(task.getDtExpireTime()).append("\n");
                content.append("请尽快完成任务。");
            }

            notice.setNoticeContent(content.toString());
            notice.setCreateBy("SYSTEM");

            int result = sysNoticeService.insertNotice(notice);
            return result > 0;
        } catch (Exception e) {
            log.error("发送系统消息失败 - taskId: " + task.getDtId(), e);
            return false;
        }
    }

    /**
     * 发送邮件（预留接口）
     */
    private boolean sendEmail(DailyTask task, String message) {
        // TODO: 集成邮件服务
        log.info("邮件通知功能待实现 - taskId: {}, userId: {}", task.getDtId(), task.getDtUserId());
        return true;  // 暂时返回成功
    }

    /**
     * 发送短信（预留接口）
     */
    private boolean sendSMS(DailyTask task, String message) {
        // TODO: 集成短信服务
        log.info("短信通知功能待实现 - taskId: {}, userId: {}", task.getDtId(), task.getDtUserId());
        return true;  // 暂时返回成功
    }
}
