package com.ruoyi.notification.task;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.notification.service.INotificationService;
import com.ruoyi.notification.service.IScheduledTaskService;
import com.ruoyi.notification.domain.NotificationMessage;
import com.ruoyi.notification.util.TaskMonitorUtil;

/**
 * 数字债权系统定时任务
 * 
 * @author ruoyi
 * @date 2025-12-19
 */
@Component("digitalCreditTask")
public class DigitalCreditTask implements Job
{
    private static final Logger log = LoggerFactory.getLogger(DigitalCreditTask.class);

    @Autowired
    private INotificationService notificationService;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        Long taskId = context.getJobDetail().getJobDataMap().getLong("taskId");
        String targetObject = context.getJobDetail().getJobDataMap().getString("targetObject");
        String targetMethod = context.getJobDetail().getJobDataMap().getString("targetMethod");
        String methodParams = context.getJobDetail().getJobDataMap().getString("methodParams");

        log.info("开始执行定时任务: taskId={}, method={}", taskId, targetMethod);

        // 记录任务开始执行
        long startTime = TaskMonitorUtil.recordTaskStart(taskId);
        
        boolean success = false;
        String errorMessage = null;
        
        try {
            // 根据方法名执行相应的任务
            if ("checkContractExpiry".equals(targetMethod)) {
                success = executeContractExpiryCheck(methodParams);
            } else if ("checkContractStatus".equals(targetMethod)) {
                success = executeContractStatusCheck();
            } else if ("sendPaymentReminder".equals(targetMethod)) {
                success = executeSendPaymentReminder(methodParams);
            } else if ("checkSystemHealth".equals(targetMethod)) {
                success = executeSystemHealthCheck();
            } else {
                log.warn("未知的任务方法: {}", targetMethod);
                success = false;
                errorMessage = "未知的任务方法: " + targetMethod;
            }

            log.info("定时任务执行完成: taskId={}, success={}", taskId, success);
        } catch (Exception e) {
            log.error("定时任务执行失败: taskId={}, error={}", taskId, e.getMessage(), e);
            success = false;
            errorMessage = e.getMessage();
        } finally {
            // 记录任务执行完成
            TaskMonitorUtil.recordTaskCompletion(taskId, startTime, success, errorMessage);
            
            // 更新数据库中的任务执行统计
            try {
                IScheduledTaskService scheduledTaskService = SpringUtils.getBean(IScheduledTaskService.class);
                scheduledTaskService.updateTaskExecutionStats(taskId, success);
            } catch (Exception e) {
                log.error("更新任务执行统计失败: {}", e.getMessage());
            }
        }

        if (!success) {
            throw new JobExecutionException("任务执行失败: taskId=" + taskId + ", error=" + errorMessage);
        }
    }

    /**
     * 检查合同到期情况
     */
    public boolean executeContractExpiryCheck(String params) {
        try {
            log.info("开始执行合同到期检查任务, 参数: {}", params);
            
            if (StringUtils.isEmpty(params)) {
                log.warn("合同到期检查任务参数为空");
                return false;
            }

            String[] paramArray = params.split(",");
            if (paramArray.length < 2) {
                log.warn("合同到期检查任务参数格式错误: {}", params);
                return false;
            }

            Long contractId = Long.parseLong(paramArray[0]);
            int reminderDays = Integer.parseInt(paramArray[1]);

            // 这里应该调用合同服务检查合同到期情况
            // 由于当前只实现通知模块，这里模拟检查逻辑
            Date currentDate = new Date();
            Date reminderDate = DateUtils.addDays(currentDate, reminderDays);
            
            log.info("检查合同 {} 是否在 {} 天内到期", contractId, reminderDays);

            // 模拟检查结果：如果合同即将到期，发送提醒通知
            if (shouldSendReminder(contractId, reminderDays)) {
                NotificationMessage message = new NotificationMessage();
                message.setNotificationId("CONTRACT_EXPIRY_" + contractId + "_" + System.currentTimeMillis());
                message.setRecipientType("CLIENT");
                message.setRecipientId("client_" + contractId);
                message.setRecipientAddress("client_" + contractId + "@example.com");
                message.setNotificationType("CONTRACT_EXPIRY_REMINDER");
                message.setNotificationChannel("EMAIL");
                message.setSubject("合同到期提醒");
                message.setContent("您的服务合同（编号：" + contractId + "）将在 " + reminderDays + " 天内到期，请及时处理相关事宜。");
                message.setPriority("HIGH");
                message.setMessageStatus("PENDING");
                message.setScheduledTime(currentDate);

                boolean sent = notificationService.sendNotification(message);
                log.info("合同到期提醒发送结果: contractId={}, sent={}", contractId, sent);
                return sent;
            } else {
                log.info("合同 {} 暂无需要发送到期提醒", contractId);
                return true;
            }
        } catch (Exception e) {
            log.error("执行合同到期检查任务失败: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 检查合同状态
     */
    public boolean executeContractStatusCheck() {
        try {
            log.info("开始执行合同状态检查任务");

            // 这里应该调用合同服务检查所有合同状态
            // 由于当前只实现通知模块，这里模拟检查逻辑
            
            // 模拟检查逻辑：检查是否有状态异常的合同
            List<Long> abnormalContracts = checkAbnormalContracts();
            
            if (!abnormalContracts.isEmpty()) {
                for (Long contractId : abnormalContracts) {
                    NotificationMessage message = new NotificationMessage();
                    message.setNotificationId("CONTRACT_STATUS_ALERT_" + contractId + "_" + System.currentTimeMillis());
                    message.setRecipientType("ADMIN");
                    message.setRecipientId("system_admin");
                    message.setRecipientAddress("admin@example.com");
                    message.setNotificationType("CONTRACT_STATUS_ALERT");
                    message.setNotificationChannel("EMAIL");
                    message.setSubject("合同状态异常告警");
                    message.setContent("合同（编号：" + contractId + "）状态异常，请及时处理。");
                    message.setPriority("HIGH");
                    message.setMessageStatus("PENDING");
                    message.setScheduledTime(new Date());

                    notificationService.sendNotification(message);
                }
                log.info("发送合同状态异常告警通知，异常合同数量: {}", abnormalContracts.size());
            } else {
                log.info("合同状态检查完成，未发现异常");
            }

            return true;
        } catch (Exception e) {
            log.error("执行合同状态检查任务失败: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 发送付款提醒
     */
    public boolean executeSendPaymentReminder(String params) {
        try {
            log.info("开始执行付款提醒任务, 参数: {}", params);
            
            if (StringUtils.isEmpty(params)) {
                log.warn("付款提醒任务参数为空");
                return false;
            }

            Long contractId = Long.parseLong(params);

            NotificationMessage message = new NotificationMessage();
            message.setNotificationId("PAYMENT_REMINDER_" + contractId + "_" + System.currentTimeMillis());
            message.setRecipientType("CLIENT");
            message.setRecipientId("client_" + contractId);
            message.setRecipientAddress("client_" + contractId + "@example.com");
            message.setNotificationType("PAYMENT_REMINDER");
            message.setNotificationChannel("EMAIL");
            message.setSubject("付款提醒");
            message.setContent("您的服务合同（编号：" + contractId + "）付款日期临近，请及时支付相关费用。");
            message.setPriority("HIGH");
            message.setMessageStatus("PENDING");
            message.setScheduledTime(new Date());

            boolean sent = notificationService.sendNotification(message);
            log.info("付款提醒发送结果: contractId={}, sent={}", contractId, sent);
            return sent;
        } catch (Exception e) {
            log.error("执行付款提醒任务失败: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 系统健康检查
     */
    public boolean executeSystemHealthCheck() {
        try {
            log.info("开始执行系统健康检查任务");

            // 模拟系统健康检查逻辑
            boolean systemHealthy = checkSystemHealth();
            
            if (!systemHealthy) {
                NotificationMessage message = new NotificationMessage();
                message.setNotificationId("SYSTEM_HEALTH_ALERT_" + System.currentTimeMillis());
                message.setRecipientType("ADMIN");
                message.setRecipientId("system_admin");
                message.setRecipientAddress("admin@example.com");
                message.setNotificationType("SYSTEM_HEALTH_ALERT");
                message.setNotificationChannel("EMAIL");
                message.setSubject("系统健康状态告警");
                message.setContent("系统健康检查发现异常，请及时处理。检查时间：" + DateUtils.getTime());
                message.setPriority("URGENT");
                message.setMessageStatus("PENDING");
                message.setScheduledTime(new Date());

                notificationService.sendNotification(message);
                log.warn("系统健康检查发现异常，已发送告警通知");
            } else {
                log.info("系统健康检查正常");
            }

            return true;
        } catch (Exception e) {
            log.error("执行系统健康检查任务失败: {}", e.getMessage(), e);
            return false;
        }
    }

    /**
     * 无参数方法示例
     */
    public void ryNoParams()
    {
        log.info("执行无参数定时任务方法");
    }

    /**
     * 有参数方法示例
     */
    public void ryParams(String params)
    {
        log.info("执行有参数定时任务方法: {}", params);
    }

    /**
     * 多参数方法示例
     */
    public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i)
    {
        log.info("执行多参数定时任务方法: 字符串={}, 布尔={}, 长整型={}, 浮点型={}, 整型={}", s, b, l, d, i);
    }

    /**
     * 判断是否应该发送提醒
     * 这里是模拟逻辑，实际应该查询数据库
     */
    private boolean shouldSendReminder(Long contractId, int reminderDays) {
        // 模拟逻辑：随机决定是否需要发送提醒
        // 实际应该查询合同表，检查到期日期
        return contractId % 3 == 0; // 简单的模拟逻辑
    }

    /**
     * 检查异常合同
     * 这里是模拟逻辑，实际应该查询数据库
     */
    private List<Long> checkAbnormalContracts() {
        // 模拟逻辑：返回一些异常合同ID
        // 实际应该查询合同表，检查状态异常的合同
        return java.util.Arrays.asList(1001L, 1002L);
    }

    /**
     * 检查系统健康状态
     * 这里是模拟逻辑，实际应该检查各种系统指标
     */
    private boolean checkSystemHealth() {
        // 模拟逻辑：检查系统各项指标
        // 实际应该检查数据库连接、缓存状态、区块链连接等
        try {
            // 模拟检查数据库连接
            Thread.sleep(100);
            
            // 模拟检查缓存状态
            Thread.sleep(50);
            
            // 模拟检查区块链连接
            Thread.sleep(200);
            
            // 随机返回健康状态
            return System.currentTimeMillis() % 10 != 0;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
    }
}