package com.example.demo.model;

import java.time.LocalDateTime;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

import com.example.demo.model.enums.CommonTaskType;

/**
 * 任务队列实体（task_queue 表）
 * 
 * 职责：任务调度与执行引擎的持久化层。
 * - 用户提交任务后先入此表排队（PENDING）
 * - TaskQueueService 通过内存 BlockingQueue 消费，状态变为 PROCESSING
 * - 任务执行完毕后更新为 COMPLETED 或 FAILED
 * 
 * 注意：此表与 task_status 表职责不同，不可合并。
 * task_queue 负责"调度执行"，task_status 负责"轮询外部 API 结果"。
 * 
 * @see TaskStatus
 * @see com.example.demo.service.TaskQueueService
 */
@Entity
@Table(name = "task_queue")
public class TaskQueue {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "username", nullable = false, length = 100)
    private String username;

    @Column(name = "task_id", nullable = false, length = 50)
    private String taskId;

    @Enumerated(EnumType.STRING)
    @Column(name = "task_type", nullable = false, length = 20)
    private CommonTaskType taskType;

    @Enumerated(EnumType.STRING)
    @Column(name = "status", nullable = false, length = 20)
    private QueueStatus status;

    @Column(name = "priority", nullable = false)
    private Integer priority = 0; // 优先级，数字越小优先级越高

    @Column(name = "real_task_id", length = 100)
    private String realTaskId; // 外部API返回的真实任务ID

    @Column(name = "last_check_time")
    private LocalDateTime lastCheckTime; // 最后一次检查时间

    @Column(name = "check_count", nullable = false)
    private Integer checkCount = 0; // 检查次数

    @Column(name = "max_check_count", nullable = false)
    private Integer maxCheckCount = 5; // 最大检查次数（5次 * 2分钟 = 10分钟）

    @Column(name = "error_message", columnDefinition = "TEXT")
    private String errorMessage;

    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;

    @Column(name = "updated_at", nullable = false)
    private LocalDateTime updatedAt;

    @Column(name = "completed_at")
    private LocalDateTime completedAt;

    /**
     * 任务类型枚举
     */
    // TaskType 枚举已统一到 com.example.demo.model.enums.CommonTaskType

    /**
     * 队列状态枚举
     */
    public enum QueueStatus {
        PENDING("等待中"),
        PROCESSING("处理中"),
        COMPLETED("已完成"),
        FAILED("失败"),
        CANCELLED("已取消"),
        TIMEOUT("超时");

        private final String description;

        QueueStatus(String description) {
            this.description = description;
        }

        public String getDescription() {
            return description;
        }
    }

    // 构造函数
    public TaskQueue() {
        this.createdAt = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }

    public TaskQueue(String username, String taskId, CommonTaskType taskType) {
        this();
        this.username = username;
        this.taskId = taskId;
        this.taskType = taskType;
        this.status = QueueStatus.PENDING;
    }

    /**
     * 更新状态
     */
    public void updateStatus(QueueStatus newStatus) {
        this.status = newStatus;
        this.updatedAt = LocalDateTime.now();
        
        if (newStatus == QueueStatus.COMPLETED || 
            newStatus == QueueStatus.FAILED || 
            newStatus == QueueStatus.CANCELLED ||
            newStatus == QueueStatus.TIMEOUT) {
            this.completedAt = LocalDateTime.now();
        }
    }

    /**
     * 增加检查次数
     */
    public void incrementCheckCount() {
        this.checkCount++;
        this.lastCheckTime = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }

    /**
     * 检查是否超时
     */
    public boolean isTimeout() {
        return this.checkCount >= this.maxCheckCount;
    }

    /**
     * 检查是否可以处理
     */
    public boolean canProcess() {
        return this.status == QueueStatus.PENDING || this.status == QueueStatus.PROCESSING;
    }

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public CommonTaskType getTaskType() {
        return taskType;
    }

    public void setTaskType(CommonTaskType taskType) {
        this.taskType = taskType;
    }

    public QueueStatus getStatus() {
        return status;
    }

    public void setStatus(QueueStatus status) {
        this.status = status;
    }

    public Integer getPriority() {
        return priority;
    }

    public void setPriority(Integer priority) {
        this.priority = priority;
    }

    public String getRealTaskId() {
        return realTaskId;
    }

    public void setRealTaskId(String realTaskId) {
        this.realTaskId = realTaskId;
    }

    public LocalDateTime getLastCheckTime() {
        return lastCheckTime;
    }

    public void setLastCheckTime(LocalDateTime lastCheckTime) {
        this.lastCheckTime = lastCheckTime;
    }

    public Integer getCheckCount() {
        return checkCount;
    }

    public void setCheckCount(Integer checkCount) {
        this.checkCount = checkCount;
    }

    public Integer getMaxCheckCount() {
        return maxCheckCount;
    }

    public void setMaxCheckCount(Integer maxCheckCount) {
        this.maxCheckCount = maxCheckCount;
    }

    public String getErrorMessage() {
        return errorMessage;
    }

    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }

    public LocalDateTime getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(LocalDateTime createdAt) {
        this.createdAt = createdAt;
    }

    public LocalDateTime getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(LocalDateTime updatedAt) {
        this.updatedAt = updatedAt;
    }

    public LocalDateTime getCompletedAt() {
        return completedAt;
    }

    public void setCompletedAt(LocalDateTime completedAt) {
        this.completedAt = completedAt;
    }
}















