package com.mosquito.project.permission;

import com.mosquito.project.permission.SysApprovalRecord;
import com.mosquito.project.permission.ApprovalRecordRepository;
import com.mosquito.project.permission.ApprovalFlowRepository;
import com.mosquito.project.permission.DepartmentRepository;
import com.mosquito.project.permission.SysDepartment;
import com.mosquito.project.permission.UserRepository;
import com.mosquito.project.permission.entity.SysUserEntity;
import com.mosquito.project.service.NotificationService;
import com.mosquito.project.service.EmailService;
import com.mosquito.project.service.SmsService;
import com.mosquito.project.persistence.entity.NotificationEntity;
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.springframework.transaction.annotation.Transactional;

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

/**
 * 审批超时处理定时任务
 * TASK-317: 审批超时检测
 * TASK-318: 超时提醒通知
 * TASK-319: 超时自动升级
 */
@Component
public class ApprovalTimeoutJob {

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

    private final ApprovalRecordRepository recordRepository;
    private final ApprovalFlowRepository flowRepository;
    private final ApprovalFlowService approvalFlowService;
    private final DepartmentRepository departmentRepository;
    private final NotificationService notificationService;
    private final ApprovalTimeoutReminderRepository reminderRepository;
    private final UserRepository userRepository;
    private EmailService emailService;
    private SmsService smsService;

    public ApprovalTimeoutJob(
            ApprovalRecordRepository recordRepository,
            ApprovalFlowRepository flowRepository,
            ApprovalFlowService approvalFlowService,
            DepartmentRepository departmentRepository,
            NotificationService notificationService,
            ApprovalTimeoutReminderRepository reminderRepository,
            UserRepository userRepository) {
        this.recordRepository = recordRepository;
        this.flowRepository = flowRepository;
        this.approvalFlowService = approvalFlowService;
        this.departmentRepository = departmentRepository;
        this.notificationService = notificationService;
        this.reminderRepository = reminderRepository;
        this.userRepository = userRepository;
    }

    @Autowired(required = false)
    public void setEmailService(EmailService emailService) {
        this.emailService = emailService;
    }

    @Autowired(required = false)
    public void setSmsService(SmsService smsService) {
        this.smsService = smsService;
    }

    /**
     * 每小时执行一次审批超时检测
     * TASK-317: 审批超时检测
     */
    @Scheduled(fixedRate = 3600000) // 每小时执行一次
    @Transactional
    public void checkApprovalTimeout() {
        log.info("开始执行审批超时检测任务");

        List<SysApprovalRecord> processingRecords = recordRepository.findByStatus("PROCESSING");

        for (SysApprovalRecord record : processingRecords) {
            try {
                processTimeoutRecord(record);
            } catch (Exception e) {
                log.error("处理审批超时记录失败, recordId: {}", record.getId(), e);
            }
        }

        log.info("审批超时检测任务执行完成, 共处理 {} 条记录", processingRecords.size());
    }

    /**
     * 处理超时记录
     * TASK-318: 超时提醒通知
     * TASK-319: 超时自动升级
     * PRD要求：50%触发首次提醒，80%二次提醒，100%自动升级
     */
    private void processTimeoutRecord(SysApprovalRecord record) {
        // 获取流程配置
        var flowOpt = flowRepository.findById(record.getFlowId());
        if (flowOpt.isEmpty()) {
            log.warn("审批记录 {} 对应的流程配置不存在", record.getId());
            return;
        }

        var flow = flowOpt.get();
        Integer timeoutHours = flow.getTimeoutHours();
        if (timeoutHours == null || timeoutHours <= 0) {
            timeoutHours = 24; // 默认24小时
        }

        LocalDateTime createdAt = record.getCreatedAt();
        if (createdAt == null) {
            createdAt = LocalDateTime.now();
        }

        LocalDateTime deadline = createdAt.plusHours(timeoutHours);
        LocalDateTime now = LocalDateTime.now();

        // 计算进度百分比 (0-100)
        long totalMillis = java.time.Duration.between(createdAt, deadline).toMillis();
        long elapsedMillis = java.time.Duration.between(createdAt, now).toMillis();
        int progressPercent = totalMillis > 0 ? (int) ((elapsedMillis * 100) / totalMillis) : 100;

        // 100% - 超时处理
        if (now.isAfter(deadline) || progressPercent >= 100) {
            handleTimeout(record, flow, timeoutHours);
        }
        // 80% - 第二次提醒
        else if (progressPercent >= 80) {
            sendTimeoutWarning(record, flow, timeoutHours, 80);
        }
        // 50% - 第一次提醒
        else if (progressPercent >= 50) {
            sendTimeoutWarning(record, flow, timeoutHours, 50);
        }
    }

    /**
     * 处理超时 - 自动升级或通知
     * TASK-319: 超时自动升级
     */
    private void handleTimeout(SysApprovalRecord record, com.mosquito.project.permission.SysApprovalFlow flow, int timeoutHours) {
        String timeoutAction = flow.getTimeoutAction();
        if (timeoutAction == null) {
            timeoutAction = "ESCALATE";
        }

        log.info("审批记录 {} 已超时 {} 小时，执行动作: {}",
                record.getId(), timeoutHours, timeoutAction);

        switch (timeoutAction) {
            case "ESCALATE":
                // 自动升级到上级审批人
                escalateApproval(record);
                break;
            case "AUTO_APPROVE":
                // 自动通过（适用于某些场景）
                autoApprove(record);
                break;
            case "NOTIFY":
                // 发送超时通知
                notifyTimeout(record);
                break;
            case "REJECT":
                // 自动拒绝
                autoReject(record);
                break;
            default:
                log.warn("未知的超时处理动作: {}", timeoutAction);
        }
    }

    /**
     * 升级审批到上级
     */
    private void escalateApproval(SysApprovalRecord record) {
        try {
            // 获取当前审批人所在部门
            Long currentApproverId = record.getCurrentApproverId();
            if (currentApproverId != null) {
                // 查找上级审批人 - 通过部门层级获取
                Optional<Long> superiorApproverId = findSuperiorApprover(currentApproverId);
                if (superiorApproverId.isPresent()) {
                    Long newApproverId = superiorApproverId.get();
                    record.setCurrentApproverId(newApproverId);
                    recordRepository.save(record);
                    log.info("审批记录 {} 已升级到上级审批人: {}", record.getId(), newApproverId);
                } else {
                    // 没有上级，通知超级管理员
                    notifyTimeout(record);
                    log.warn("审批记录 {} 无法找到上级审批人，已通知管理员", record.getId());
                }
            }
        } catch (Exception e) {
            log.error("升级审批失败, recordId: {}", record.getId(), e);
        }
    }

    /**
     * 查找上级审批人
     * 策略：根据当前审批人所在部门，查找上级部门负责人
     * 实现：先查找上级部门，如果没有上级部门则查找本部门的其他活跃用户
     */
    private Optional<Long> findSuperiorApprover(Long currentApproverId) {
        log.debug("查找用户 {} 的上级审批人", currentApproverId);

        try {
            // 1. 获取当前用户的部门ID
            var userOpt = userRepository.findById(currentApproverId);
            if (userOpt.isEmpty()) {
                log.warn("用户 {} 不存在，无法查找上级审批人", currentApproverId);
                return Optional.empty();
            }

            var user = userOpt.get();
            Long currentDeptId = user.getDepartmentId();

            if (currentDeptId == null) {
                log.warn("用户 {} 没有所属部门，无法查找上级审批人", currentApproverId);
                // 没有部门时，尝试找超级管理员作为上级
                return Optional.of(1L);
            }

            // 2. 查找上级部门
            var currentDeptOpt = departmentRepository.findById(currentDeptId);
            if (currentDeptOpt.isEmpty()) {
                log.warn("部门 {} 不存在，无法查找上级审批人", currentDeptId);
                return Optional.of(1L);
            }

            var currentDept = currentDeptOpt.get();
            Long parentDeptId = currentDept.getParentId();

            if (parentDeptId != null) {
                // 3a. 有上级部门，查找上级部门的负责人
                var parentDeptOpt = departmentRepository.findById(parentDeptId);
                if (parentDeptOpt.isPresent()) {
                    // 查找上级部门下的活跃用户
                    List<SysUserEntity> parentDeptUsers = userRepository
                            .findByDepartmentIdAndStatusNot(parentDeptId, "FROZEN");
                    if (!parentDeptUsers.isEmpty()) {
                        // 返回上级部门的第一个活跃用户作为审批人
                        Long superiorId = parentDeptUsers.get(0).getId();
                        log.info("找到用户 {} 的上级审批人: {} (部门: {})",
                                currentApproverId, superiorId, parentDeptId);
                        return Optional.of(superiorId);
                    }
                }
                log.warn("上级部门 {} 没有可用的审批用户", parentDeptId);
            }

            // 3b. 没有上级部门或上级部门没有用户，查找本部门的其他活跃用户
            log.info("用户 {} 所在部门已是顶级部门，查找本部门其他审批人", currentApproverId);
            List<SysUserEntity> sameDeptUsers = userRepository
                    .findByDepartmentIdAndStatusNot(currentDeptId, "FROZEN");
            // 排除当前用户
            sameDeptUsers.removeIf(u -> u.getId().equals(currentApproverId));
            if (!sameDeptUsers.isEmpty()) {
                Long alternateId = sameDeptUsers.get(0).getId();
                log.info("找到本部门其他审批人: {}", alternateId);
                return Optional.of(alternateId);
            }

            // 4. 兜底：返回超级管理员
            log.warn("无法找到合适的审批人，返回超级管理员作为兜底");
            return Optional.of(1L);

        } catch (Exception e) {
            log.error("查找用户 {} 的上级审批人失败: {}", currentApproverId, e.getMessage());
            // 兜底返回超级管理员
            return Optional.of(1L);
        }
    }

    /**
     * 自动通过审批
     */
    private void autoApprove(SysApprovalRecord record) {
        try {
            // 自动通过审批
            log.info("审批记录 {} 自动通过（超时自动审批）", record.getId());

            // 更新审批记录状态为已通过
            record.setStatus("APPROVED");
            record.setUpdatedAt(LocalDateTime.now());
            // 使用 bizData 存储审批备注
            record.setBizData("{\"autoApproved\":true,\"reason\":\"审批超时自动通过\"}");
            recordRepository.save(record);

            // 触发业务处理（如活动发布、奖励发放等）
            approvalFlowService.processAfterApproval(record);

            log.info("审批记录 {} 已自动通过", record.getId());
        } catch (Exception e) {
            log.error("自动通过审批失败, recordId: {}", record.getId(), e);
        }
    }

    /**
     * 发送超时通知
     */
    private void notifyTimeout(SysApprovalRecord record) {
        // 发送超时通知 - 记录日志
        Long applicantId = record.getApplicantId();
        Long approverId = record.getCurrentApproverId();
        String traceId = UUID.randomUUID().toString().substring(0, 8);

        log.info("[{}] 发送审批超时通知: 申请人: {}, 审批人: {}, 审批记录ID: {}",
                traceId, applicantId, approverId, record.getId());

        // 1. 站内消息通知审批人（审批超时，需要处理）
        NotificationEntity notification = new NotificationEntity();
        notification.setUserId(approverId);
        notification.setTitle("审批超时提醒");
        notification.setContent("您有待处理的审批已超时，请尽快处理。审批记录ID: " + record.getId());
        notification.setType("APPROVAL_TIMEOUT");
        notification.setRelatedId(record.getId());
        notification.setRelatedType("APPROVAL");
        notification.setIsRead(false);
        notification.setCreatedAt(LocalDateTime.now());
        NotificationEntity savedNotification = notificationService.createNotification(notification);

        // 2. 站内消息通知申请人（审批超时）
        NotificationEntity applicantNotification = new NotificationEntity();
        applicantNotification.setUserId(applicantId);
        applicantNotification.setTitle("审批超时通知");
        applicantNotification.setContent("您的审批申请已超时未处理。审批记录ID: " + record.getId());
        applicantNotification.setType("APPROVAL_TIMEOUT");
        applicantNotification.setRelatedId(record.getId());
        applicantNotification.setRelatedType("APPROVAL");
        applicantNotification.setIsRead(false);
        applicantNotification.setCreatedAt(LocalDateTime.now());
        NotificationEntity savedApplicantNotification = notificationService.createNotification(applicantNotification);

        log.info("[{}] 审批超时通知已发送: 审批人通知ID: {}, 申请人通知ID: {}, 审批人ID: {}, 申请人ID: {}",
                traceId, savedNotification.getId(), savedApplicantNotification.getId(), approverId, applicantId);
    }

    /**
     * 自动拒绝
     */
    private void autoReject(SysApprovalRecord record) {
        try {
            // 自动拒绝审批
            log.info("审批记录 {} 因超时被自动拒绝", record.getId());

            // 更新审批记录状态为已拒绝
            record.setStatus("REJECTED");
            record.setUpdatedAt(LocalDateTime.now());
            // 使用 bizData 存储审批备注
            record.setBizData("{\"autoRejected\":true,\"reason\":\"审批超时自动拒绝\"}");
            recordRepository.save(record);

            // 触发业务处理（如通知申请人等）
            approvalFlowService.processAfterRejection(record);

            log.info("审批记录 {} 已自动拒绝", record.getId());
        } catch (Exception e) {
            log.error("自动拒绝审批失败, recordId: {}", record.getId(), e);
        }
    }

    /**
     * 发送超时预警通知
     * TASK-318: 超时提醒通知
     * PRD要求：
     * - 50%: 站内+邮件
     * - 80%: 站内+邮件+短信
     * - 100%: 升级通知（由handleTimeout处理）
     * @param progressPercent 当前进度百分比 (50 或 80)
     */
    private void sendTimeoutWarning(SysApprovalRecord record, com.mosquito.project.permission.SysApprovalFlow flow, int timeoutHours, int progressPercent) {
        Long applicantId = record.getApplicantId();
        Long approverId = record.getCurrentApproverId();

        // 检查是否已发送过该进度的提醒，避免重复发送
        if (reminderRepository.hasReminderBeenSent(record.getId(), approverId, progressPercent)) {
            log.debug("审批记录 {} 已发送过 {}% 提醒，跳过", record.getId(), progressPercent);
            return;
        }

        log.info("发送审批超时{}%预警: 申请人: {}, 审批人: {}, 审批记录ID: {}, 剩余{}%时间",
                progressPercent, applicantId, approverId, record.getId(), 100 - progressPercent);

        // 1. 站内消息通知（所有阶段都发送）
        NotificationEntity notification = new NotificationEntity();
        notification.setUserId(approverId);
        notification.setTitle("审批时效预警 (" + progressPercent + "%)");
        notification.setContent("您有待处理的审批即将超时（已使用" + progressPercent + "%时间），请尽快处理。审批记录ID: " + record.getId());
        notification.setType("APPROVAL_WARNING");
        notification.setRelatedId(record.getId());
        notification.setRelatedType("APPROVAL");
        notification.setIsRead(false);
        notification.setCreatedAt(LocalDateTime.now());
        notificationService.createNotification(notification);

        // 2. 邮件通知（50%和80%阶段）
        if (progressPercent == 50 || progressPercent >= 80) {
            sendEmailNotification(approverId, record, progressPercent);
        }

        // 3. 短信通知（仅80%阶段）
        if (progressPercent >= 80) {
            sendSmsNotification(approverId, record);
        }

        // 记录提醒发送记录，用于去重
        ApprovalTimeoutReminderRecord reminder = new ApprovalTimeoutReminderRecord();
        reminder.setRecordId(record.getId());
        reminder.setApproverId(approverId);
        reminder.setProgressPercent(progressPercent);
        reminder.setRemindedAt(LocalDateTime.now());
        reminderRepository.save(reminder);

        log.info("审批超时预警已发送: 审批人ID: {}, 进度: {}%", approverId, progressPercent);
    }

    /**
     * 发送邮件通知
     * 50%和80%进度时发送邮件
     */
    private void sendEmailNotification(Long approverId, SysApprovalRecord record, int progressPercent) {
        if (emailService == null) {
            log.warn("[EMAIL] 邮件服务未配置，无法发送邮件通知");
            return;
        }

        // 获取审批人邮箱
        Optional<SysUserEntity> approverOpt = userRepository.findById(approverId);
        if (approverOpt.isEmpty()) {
            log.warn("[EMAIL] 审批人不存在, approverId: {}", approverId);
            return;
        }

        SysUserEntity approver = approverOpt.get();
        String email = approver.getEmail();
        if (email == null || email.isBlank()) {
            log.warn("[EMAIL] 审批人邮箱为空, approverId: {}", approverId);
            return;
        }

        String approverName = approver.getRealName() != null ? approver.getRealName() : approver.getUsername();
        boolean success = emailService.sendApprovalTimeoutEmail(email, approverName, record.getId(), progressPercent);

        log.info("[EMAIL_NOTIFICATION] 审批超时{}%预警邮件: 审批人ID: {}, 审批记录ID: {}, 邮箱: {}, 结果: {}",
                progressPercent, approverId, record.getId(), email, success ? "成功" : "失败");
    }

    /**
     * 发送短信通知
     * 仅在80%进度时发送短信（根据PRD：80%触发站内+邮件+短信）
     */
    private void sendSmsNotification(Long approverId, SysApprovalRecord record) {
        if (smsService == null) {
            log.warn("[SMS] 短信服务未配置，无法发送短信通知");
            return;
        }

        // 获取审批人手机号
        Optional<SysUserEntity> approverOpt = userRepository.findById(approverId);
        if (approverOpt.isEmpty()) {
            log.warn("[SMS] 审批人不存在, approverId: {}", approverId);
            return;
        }

        SysUserEntity approver = approverOpt.get();
        String phone = approver.getPhone();
        if (phone == null || phone.isBlank()) {
            log.warn("[SMS] 审批人手机号为空, approverId: {}", approverId);
            return;
        }

        String approverName = approver.getRealName() != null ? approver.getRealName() : approver.getUsername();
        boolean success = smsService.sendApprovalTimeoutSms(phone, approverName, record.getId());

        log.info("[SMS_NOTIFICATION] 审批超时预警短信: 审批人ID: {}, 审批记录ID: {}, 手机号: {}, 结果: {}",
                approverId, record.getId(), phone, success ? "成功" : "失败");
    }

    /**
     * 手动触发超时检测（用于测试或管理）
     */
    public void manualCheckTimeout() {
        checkApprovalTimeout();
    }
}
