package com.example.demo.model;

import jakarta.persistence.*;
import java.time.LocalDateTime;
import com.example.demo.model.enums.CommonTaskType;

/**
 * 任务状态轮询实体（task_status 表）
 * 
 * 职责：跟踪已提交到外部 AI API 的任务的轮询状态。
 * - 任务提交到外部 API 后，在此表创建记录，存储 externalTaskId
 * - TaskStatusPollingService 定期轮询外部 API，更新 status / resultUrl
 * - 轮询完成后通过级联更新同步到 task_queue、业务任务表和 user_works
 * 
 * 注意：此表与 task_queue 表职责不同，不可合并。
 * task_status 负责"轮询外部 API 结果"，task_queue 负责"调度执行"。
 * 
 * @see TaskQueue
 * @see com.example.demo.service.TaskStatusPollingService
 */
@Entity
@Table(name = "task_status")
public class TaskStatus {
    
    // TaskType 枚举已统一到 com.example.demo.model.enums.CommonTaskType
    
    public enum Status {
        PENDING("待处理"),
        PROCESSING("处理中"),
        COMPLETED("已完成"),
        FAILED("失败"),
        CANCELLED("已取消"),
        TIMEOUT("超时");
        
        private final String description;
        
        Status(String description) {
            this.description = description;
        }
        
        public String getDescription() {
            return description;
        }
    }
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "task_id", nullable = false)
    private String taskId;
    
    @Column(name = "username", nullable = false)
    private String username;
    
    @Enumerated(EnumType.STRING)
    @Column(name = "task_type", nullable = false)
    private CommonTaskType taskType;
    
    @Enumerated(EnumType.STRING)
    @Column(name = "status", nullable = false)
    private Status status = Status.PENDING;
    
    @Column(name = "progress")
    private Integer progress = 0;
    
    @Column(name = "result_url", columnDefinition = "LONGTEXT")
    private String resultUrl;
    
    @Column(name = "error_message", columnDefinition = "TEXT")
    private String errorMessage;
    
    @Column(name = "external_task_id")
    private String externalTaskId;
    
    @Column(name = "created_at")
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;
    
    @Column(name = "completed_at")
    private LocalDateTime completedAt;
    
    @Column(name = "last_polled_at")
    private LocalDateTime lastPolledAt;
    
    @Column(name = "poll_count")
    private Integer pollCount = 0;
    
    @Column(name = "max_polls")
    private Integer maxPolls = 60; // 2小时，每2分钟一次
    
    // 构造函数
    public TaskStatus() {}
    
    public TaskStatus(String taskId, String username, CommonTaskType taskType) {
        this.taskId = taskId;
        this.username = username;
        this.taskType = taskType;
        this.createdAt = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }
    
    // Getters and Setters
    public Long getId() {
        return id;
    }
    
    public void setId(Long id) {
        this.id = id;
    }
    
    public String getTaskId() {
        return taskId;
    }
    
    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }
    
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public CommonTaskType getTaskType() {
        return taskType;
    }
    
    public void setTaskType(CommonTaskType taskType) {
        this.taskType = taskType;
    }
    
    public Status getStatus() {
        return status;
    }
    
    public void setStatus(Status status) {
        this.status = status;
    }
    
    public Integer getProgress() {
        return progress;
    }
    
    public void setProgress(Integer progress) {
        this.progress = progress;
    }
    
    public String getResultUrl() {
        return resultUrl;
    }
    
    public void setResultUrl(String resultUrl) {
        this.resultUrl = resultUrl;
    }
    
    public String getErrorMessage() {
        return errorMessage;
    }
    
    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }
    
    public String getExternalTaskId() {
        return externalTaskId;
    }
    
    public void setExternalTaskId(String externalTaskId) {
        this.externalTaskId = externalTaskId;
    }
    
    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;
    }
    
    public LocalDateTime getLastPolledAt() {
        return lastPolledAt;
    }
    
    public void setLastPolledAt(LocalDateTime lastPolledAt) {
        this.lastPolledAt = lastPolledAt;
    }
    
    public Integer getPollCount() {
        return pollCount;
    }
    
    public void setPollCount(Integer pollCount) {
        this.pollCount = pollCount;
    }
    
    public Integer getMaxPolls() {
        return maxPolls;
    }
    
    public void setMaxPolls(Integer maxPolls) {
        this.maxPolls = maxPolls;
    }
    
    // 业务方法
    public void incrementPollCount() {
        this.pollCount++;
        this.lastPolledAt = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }
    
    public boolean isPollingExpired() {
        return pollCount >= maxPolls;
    }
    
    public void markAsCompleted(String resultUrl) {
        this.status = Status.COMPLETED;
        this.resultUrl = resultUrl;
        this.progress = 100;
        this.completedAt = LocalDateTime.now();
        this.updatedAt = LocalDateTime.now();
    }
    
    public void markAsFailed(String errorMessage) {
        this.status = Status.FAILED;
        this.errorMessage = errorMessage;
        this.updatedAt = LocalDateTime.now();
    }
    
    public void markAsTimeout() {
        this.status = Status.FAILED;  // 超时也标记为 FAILED，便于前端统一处理
        this.errorMessage = "任务超时，超过最大轮询次数";
        this.updatedAt = LocalDateTime.now();
    }
}





















