package com.ruoyi.credit.service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.ruoyi.common.utils.DateUtils;

/**
 * 验证队列管理器
 * 实现验证队列和优先级管理
 * 
 * @author ruoyi
 * @date 2025-12-31
 */
@Service
public class ValidationQueueManager {

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

    @Autowired
    private ILoanConsistencyService loanConsistencyService;

    /** 验证队列最大容量 */
    @Value("${loan.validation.queue.maxSize:10000}")
    private int maxQueueSize;

    /** 队列处理线程数 */
    @Value("${loan.validation.queue.threadCount:5}")
    private int queueThreadCount;

    /** 批量处理大小 */
    @Value("${loan.validation.queue.batchSize:50}")
    private int batchSize;

    /** 队列处理间隔（毫秒） */
    @Value("${loan.validation.queue.processInterval:5000}")
    private long processInterval;

    /** 优先级验证队列 */
    private PriorityBlockingQueue<ValidationTask> priorityQueue;

    /** 延迟验证队列 */
    private DelayQueue<DelayedValidationTask> delayQueue;

    /** 正在处理的任务映射 */
    private Map<Long, ValidationTask> processingTasks;

    /** 任务ID生成器 */
    private AtomicLong taskIdGenerator;

    /** 队列处理器运行状态 */
    private volatile boolean running;

    /** 队列处理线程 */
    private Thread[] queueProcessorThreads;

    /** 延迟队列处理线程 */
    private Thread delayQueueProcessorThread;

    /**
     * 验证任务优先级枚举
     */
    public enum Priority {
        URGENT(1, "紧急"),
        HIGH(2, "高"),
        MEDIUM(3, "中"),
        LOW(4, "低");

        private final int level;
        private final String description;

        Priority(int level, String description) {
            this.level = level;
            this.description = description;
        }

        public int getLevel() {
            return level;
        }

        public String getDescription() {
            return description;
        }
    }

    /**
     * 验证任务
     */
    public static class ValidationTask implements Comparable<ValidationTask> {
        private Long taskId;
        private Long loanId;
        private Priority priority;
        private String reason;
        private Date createTime;
        private Date scheduleTime;
        private int retryCount;
        private int maxRetries;

        public ValidationTask(Long taskId, Long loanId, Priority priority, String reason) {
            this.taskId = taskId;
            this.loanId = loanId;
            this.priority = priority;
            this.reason = reason;
            this.createTime = DateUtils.getNowDate();
            this.scheduleTime = DateUtils.getNowDate();
            this.retryCount = 0;
            this.maxRetries = 3;
        }

        @Override
        public int compareTo(ValidationTask other) {
            // 优先级越小，优先级越高
            int priorityCompare = Integer.compare(this.priority.getLevel(), other.priority.getLevel());
            if (priorityCompare != 0) {
                return priorityCompare;
            }
            // 优先级相同时，按创建时间排序
            return this.createTime.compareTo(other.createTime);
        }

        // Getters and Setters
        public Long getTaskId() { return taskId; }
        public void setTaskId(Long taskId) { this.taskId = taskId; }
        
        public Long getLoanId() { return loanId; }
        public void setLoanId(Long loanId) { this.loanId = loanId; }
        
        public Priority getPriority() { return priority; }
        public void setPriority(Priority priority) { this.priority = priority; }
        
        public String getReason() { return reason; }
        public void setReason(String reason) { this.reason = reason; }
        
        public Date getCreateTime() { return createTime; }
        public void setCreateTime(Date createTime) { this.createTime = createTime; }
        
        public Date getScheduleTime() { return scheduleTime; }
        public void setScheduleTime(Date scheduleTime) { this.scheduleTime = scheduleTime; }
        
        public int getRetryCount() { return retryCount; }
        public void setRetryCount(int retryCount) { this.retryCount = retryCount; }
        
        public int getMaxRetries() { return maxRetries; }
        public void setMaxRetries(int maxRetries) { this.maxRetries = maxRetries; }

        public void incrementRetryCount() {
            this.retryCount++;
        }

        public boolean canRetry() {
            return this.retryCount < this.maxRetries;
        }

        @Override
        public String toString() {
            return "ValidationTask{" +
                    "taskId=" + taskId +
                    ", loanId=" + loanId +
                    ", priority=" + priority +
                    ", reason='" + reason + '\'' +
                    ", createTime=" + createTime +
                    ", retryCount=" + retryCount +
                    '}';
        }
    }

    /**
     * 延迟验证任务
     */
    public static class DelayedValidationTask implements Delayed {
        private ValidationTask task;
        private long executeTime;

        public DelayedValidationTask(ValidationTask task, long delayMillis) {
            this.task = task;
            this.executeTime = System.currentTimeMillis() + delayMillis;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(executeTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
        }

        @Override
        public int compareTo(Delayed other) {
            if (other instanceof DelayedValidationTask) {
                return Long.compare(this.executeTime, ((DelayedValidationTask) other).executeTime);
            }
            return 0;
        }

        public ValidationTask getTask() {
            return task;
        }

        public long getExecuteTime() {
            return executeTime;
        }
    }

    /**
     * 初始化队列管理器
     */
    @PostConstruct
    public void initialize() {
        log.info("初始化验证队列管理器，最大队列容量: {}, 处理线程数: {}", maxQueueSize, queueThreadCount);

        // 初始化队列
        this.priorityQueue = new PriorityBlockingQueue<>(maxQueueSize);
        this.delayQueue = new DelayQueue<>();
        this.processingTasks = new ConcurrentHashMap<>();
        this.taskIdGenerator = new AtomicLong(0);
        this.running = true;

        // 启动队列处理线程
        startQueueProcessorThreads();

        // 启动延迟队列处理线程
        startDelayQueueProcessorThread();

        log.info("验证队列管理器初始化完成");
    }

    /**
     * 销毁队列管理器
     */
    @PreDestroy
    public void destroy() {
        log.info("开始销毁验证队列管理器");

        this.running = false;

        // 停止队列处理线程
        if (queueProcessorThreads != null) {
            for (Thread thread : queueProcessorThreads) {
                if (thread != null) {
                    thread.interrupt();
                }
            }
        }

        // 停止延迟队列处理线程
        if (delayQueueProcessorThread != null) {
            delayQueueProcessorThread.interrupt();
        }

        log.info("验证队列管理器销毁完成");
    }

    /**
     * 添加验证任务到队列
     * 
     * @param loanId 贷款ID
     * @param priority 优先级
     * @param reason 验证原因
     * @return 任务ID
     */
    public Long addToValidationQueue(Long loanId, Priority priority, String reason) {
        if (loanId == null) {
            throw new IllegalArgumentException("贷款ID不能为空");
        }

        // 检查是否已经在处理中
        if (processingTasks.containsKey(loanId)) {
            log.debug("贷款ID: {} 已在处理队列中，跳过添加", loanId);
            return null;
        }

        // 检查队列容量
        if (priorityQueue.size() >= maxQueueSize) {
            log.warn("验证队列已满，无法添加新任务，贷款ID: {}", loanId);
            return null;
        }

        Long taskId = taskIdGenerator.incrementAndGet();
        ValidationTask task = new ValidationTask(taskId, loanId, priority, reason);

        boolean added = priorityQueue.offer(task);
        if (added) {
            log.info("验证任务已添加到队列，任务ID: {}, 贷款ID: {}, 优先级: {}, 原因: {}", 
                taskId, loanId, priority.getDescription(), reason);
            return taskId;
        } else {
            log.error("添加验证任务到队列失败，贷款ID: {}", loanId);
            return null;
        }
    }

    /**
     * 添加延迟验证任务
     * 
     * @param loanId 贷款ID
     * @param priority 优先级
     * @param reason 验证原因
     * @param delayMillis 延迟时间（毫秒）
     * @return 任务ID
     */
    public Long addToDelayedValidationQueue(Long loanId, Priority priority, String reason, long delayMillis) {
        if (loanId == null) {
            throw new IllegalArgumentException("贷款ID不能为空");
        }

        Long taskId = taskIdGenerator.incrementAndGet();
        ValidationTask task = new ValidationTask(taskId, loanId, priority, reason);
        DelayedValidationTask delayedTask = new DelayedValidationTask(task, delayMillis);

        boolean added = delayQueue.offer(delayedTask);
        if (added) {
            log.info("延迟验证任务已添加到队列，任务ID: {}, 贷款ID: {}, 延迟时间: {}ms", 
                taskId, loanId, delayMillis);
            return taskId;
        } else {
            log.error("添加延迟验证任务到队列失败，贷款ID: {}", loanId);
            return null;
        }
    }

    /**
     * 获取队列状态信息
     * 
     * @return 队列状态
     */
    public Map<String, Object> getQueueStatus() {
        Map<String, Object> status = new ConcurrentHashMap<>();
        status.put("priorityQueueSize", priorityQueue.size());
        status.put("delayQueueSize", delayQueue.size());
        status.put("processingTasksCount", processingTasks.size());
        status.put("maxQueueSize", maxQueueSize);
        status.put("queueThreadCount", queueThreadCount);
        status.put("running", running);
        status.put("totalTasksGenerated", taskIdGenerator.get());
        
        return status;
    }

    /**
     * 清空验证队列
     */
    public void clearQueue() {
        log.info("开始清空验证队列");
        
        int priorityQueueSize = priorityQueue.size();
        int delayQueueSize = delayQueue.size();
        
        priorityQueue.clear();
        delayQueue.clear();
        processingTasks.clear();
        
        log.info("验证队列清空完成，清除优先级队列任务: {}, 延迟队列任务: {}", priorityQueueSize, delayQueueSize);
    }

    /**
     * 启动队列处理线程
     */
    private void startQueueProcessorThreads() {
        queueProcessorThreads = new Thread[queueThreadCount];
        
        for (int i = 0; i < queueThreadCount; i++) {
            final int threadIndex = i;
            queueProcessorThreads[i] = new Thread(() -> processValidationQueue(threadIndex), 
                "ValidationQueueProcessor-" + threadIndex);
            queueProcessorThreads[i].setDaemon(true);
            queueProcessorThreads[i].start();
        }
        
        log.info("启动了 {} 个队列处理线程", queueThreadCount);
    }

    /**
     * 启动延迟队列处理线程
     */
    private void startDelayQueueProcessorThread() {
        delayQueueProcessorThread = new Thread(this::processDelayQueue, "DelayedValidationQueueProcessor");
        delayQueueProcessorThread.setDaemon(true);
        delayQueueProcessorThread.start();
        
        log.info("启动延迟队列处理线程");
    }

    /**
     * 处理验证队列
     * 
     * @param threadIndex 线程索引
     */
    private void processValidationQueue(int threadIndex) {
        log.info("队列处理线程 {} 开始运行", threadIndex);
        
        while (running) {
            try {
                ValidationTask task = priorityQueue.take(); // 阻塞等待任务
                
                if (task != null) {
                    processValidationTask(task, threadIndex);
                }
                
            } catch (InterruptedException e) {
                log.info("队列处理线程 {} 被中断", threadIndex);
                Thread.currentThread().interrupt();
                break;
            } catch (Exception e) {
                log.error("队列处理线程 {} 处理任务异常", threadIndex, e);
            }
        }
        
        log.info("队列处理线程 {} 结束运行", threadIndex);
    }

    /**
     * 处理延迟队列
     */
    private void processDelayQueue() {
        log.info("延迟队列处理线程开始运行");
        
        while (running) {
            try {
                DelayedValidationTask delayedTask = delayQueue.take(); // 阻塞等待到期任务
                
                if (delayedTask != null) {
                    ValidationTask task = delayedTask.getTask();
                    log.debug("延迟任务到期，将任务添加到优先级队列，任务ID: {}", task.getTaskId());
                    
                    // 将到期的延迟任务添加到优先级队列
                    priorityQueue.offer(task);
                }
                
            } catch (InterruptedException e) {
                log.info("延迟队列处理线程被中断");
                Thread.currentThread().interrupt();
                break;
            } catch (Exception e) {
                log.error("延迟队列处理线程处理任务异常", e);
            }
        }
        
        log.info("延迟队列处理线程结束运行");
    }

    /**
     * 处理单个验证任务
     * 
     * @param task 验证任务
     * @param threadIndex 线程索引
     */
    private void processValidationTask(ValidationTask task, int threadIndex) {
        log.debug("线程 {} 开始处理验证任务: {}", threadIndex, task);
        
        try {
            // 标记任务为处理中
            processingTasks.put(task.getLoanId(), task);
            
            // 执行验证
            loanConsistencyService.validateLoanConsistency(task.getLoanId(), null, null);
            
            log.info("线程 {} 完成验证任务，任务ID: {}, 贷款ID: {}", 
                threadIndex, task.getTaskId(), task.getLoanId());
            
        } catch (Exception e) {
            log.error("线程 {} 处理验证任务失败，任务ID: {}, 贷款ID: {}", 
                threadIndex, task.getTaskId(), task.getLoanId(), e);
            
            // 处理重试逻辑
            handleTaskRetry(task, e);
            
        } finally {
            // 移除处理中标记
            processingTasks.remove(task.getLoanId());
        }
    }

    /**
     * 处理任务重试
     * 
     * @param task 验证任务
     * @param exception 异常信息
     */
    private void handleTaskRetry(ValidationTask task, Exception exception) {
        if (task.canRetry()) {
            task.incrementRetryCount();
            
            // 计算重试延迟时间（指数退避）
            long retryDelay = (long) (Math.pow(2, task.getRetryCount()) * 1000); // 2^n 秒
            
            log.info("任务重试，任务ID: {}, 贷款ID: {}, 重试次数: {}/{}, 延迟: {}ms", 
                task.getTaskId(), task.getLoanId(), task.getRetryCount(), task.getMaxRetries(), retryDelay);
            
            // 添加到延迟队列进行重试
            DelayedValidationTask retryTask = new DelayedValidationTask(task, retryDelay);
            delayQueue.offer(retryTask);
            
        } else {
            log.error("任务重试次数已达上限，放弃重试，任务ID: {}, 贷款ID: {}", 
                task.getTaskId(), task.getLoanId());
        }
    }
}