package org.xyzh.message.scheduler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.xyzh.common.dto.message.TbSysMessage;
import org.xyzh.message.mapper.MessageMapper;
import org.xyzh.message.service.impl.MessageSendService;

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

/**
 * 消息定时任务扫描器
 *
 * @description 定时扫描待发送的定时消息并触发发送
 * @filename MessageScheduler.java
 * @author Claude
 * @copyright xyzh
 * @since 2025-11-13
 */
@Component
public class MessageScheduler {

    private static final Logger logger = LoggerFactory.getLogger(MessageScheduler.class);

    @Autowired
    private MessageMapper messageMapper;

    @Autowired
    private MessageSendService messageSendService;

    /**
     * 扫描待发送的定时消息
     * 每分钟执行一次
     */
    @Scheduled(cron = "0 * * * * ?")
    public void scanPendingScheduledMessages() {
        try {
            logger.debug("开始扫描待发送的定时消息...");

            LocalDateTime now = LocalDateTime.now();

            // 查询满足条件的消息：
            // 1. status=pending（待发送）
            // 2. sendMode=scheduled（定时发送）
            // 3. scheduledTime <= 当前时间
            // 4. deleted=0（未删除）
            List<TbSysMessage> messages = messageMapper.selectPendingScheduledMessages(now);

            if (messages.isEmpty()) {
                logger.debug("没有待发送的定时消息");
                return;
            }

            logger.info("发现 {} 条待发送的定时消息", messages.size());

            // 处理每条消息
            for (TbSysMessage message : messages) {
                try {
                    // 使用CAS（Compare-And-Set）更新状态，防止并发重复触发
                    boolean updated = messageMapper.compareAndSetStatus(
                        message.getMessageID(),
                        "pending",    // 期望的当前状态
                        "sending"     // 新状态
                    ) > 0;

                    if (!updated) {
                        logger.warn("消息 {} 状态已被修改，跳过处理", message.getMessageID());
                        continue;
                    }

                    // 更新实际发送时间和状态
                    message.setActualSendTime(new Date());
                    message.setStatus("sending");
                    message.setUpdateTime(new Date());
                    messageMapper.updateMessage(message);

                    // 异步发送消息
                    messageSendService.sendMessageAsync(message.getMessageID());

                    logger.info("定时消息 {} 已触发发送", message.getMessageID());

                } catch (Exception e) {
                    logger.error("处理定时消息失败：{}", message.getMessageID(), e);
                    handleSendError(message, e);
                }
            }

            logger.info("定时消息扫描完成，已处理 {} 条消息", messages.size());

        } catch (Exception e) {
            logger.error("扫描定时消息时发生错误", e);
        }
    }

    /**
     * 处理发送失败，支持重试机制
     *
     * @param message 消息对象
     * @param e 异常信息
     */
    private void handleSendError(TbSysMessage message, Exception e) {
        try {
            int retryCount = message.getRetryCount() != null ? message.getRetryCount() : 0;
            int maxRetryCount = message.getMaxRetryCount() != null ? message.getMaxRetryCount() : 3;

            if (retryCount < maxRetryCount) {
                // 未达到最大重试次数，增加重试计数
                message.setRetryCount(retryCount + 1);
                message.setStatus("pending");  // 重新置为待发送状态

                // 设置下次重试时间（5分钟后）
                LocalDateTime nextRetryTime = LocalDateTime.now().plusMinutes(5);
                message.setScheduledTime(convertToDate(nextRetryTime));

                message.setLastError(e.getMessage());
                message.setUpdateTime(new Date());
                messageMapper.updateMessage(message);

                logger.warn("消息 {} 发送失败，将在5分钟后重试 ({}/{})",
                    message.getMessageID(), retryCount + 1, maxRetryCount);

            } else {
                // 超过最大重试次数，标记为失败
                message.setStatus("failed");
                message.setLastError("超过最大重试次数：" + e.getMessage());
                message.setUpdateTime(new Date());
                messageMapper.updateMessage(message);

                logger.error("消息 {} 发送失败且已超过最大重试次数", message.getMessageID());
            }

        } catch (Exception ex) {
            logger.error("处理发送错误时发生异常", ex);
        }
    }

    /**
     * 将LocalDateTime转换为Date
     */
    private Date convertToDate(LocalDateTime localDateTime) {
        return java.sql.Timestamp.valueOf(localDateTime);
    }

    /**
     * 每小时清理一次已取消和已失败的旧消息（可选功能）
     * 将超过30天的已取消/失败消息标记为删除
     */
    @Scheduled(cron = "0 0 * * * ?")
    public void cleanupOldMessages() {
        try {
            logger.debug("开始清理旧消息...");

            // 计算30天前的时间
            LocalDateTime thirtyDaysAgo = LocalDateTime.now().minusDays(30);

            // TODO: 实现清理逻辑
            // 清理条件：
            // 1. status in ('cancelled', 'failed')
            // 2. updateTime < 30天前
            // 3. deleted = 0

            logger.debug("旧消息清理完成");

        } catch (Exception e) {
            logger.error("清理旧消息时发生错误", e);
        }
    }

    /**
     * 每天凌晨生成消息统计报告（可选功能）
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void generateDailyReport() {
        try {
            logger.info("开始生成每日消息统计报告...");

            // TODO: 实现统计报告生成逻辑
            // 统计内容：
            // 1. 今日发送消息总数
            // 2. 发送成功率
            // 3. 已读率
            // 4. 各发送方式的使用情况

            logger.info("每日消息统计报告生成完成");

        } catch (Exception e) {
            logger.error("生成每日报告时发生错误", e);
        }
    }
}
