package com.example.demo.repository;

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

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Lock;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import com.example.demo.model.TaskQueue;

import jakarta.persistence.LockModeType;

/**
 * 任务队列仓库接口
 */
@Repository
public interface TaskQueueRepository extends JpaRepository<TaskQueue, Long> {

    /**
     * 根据用户名查找待处理的任务
     */
    @Query("SELECT tq FROM TaskQueue tq WHERE tq.username = :username AND tq.status IN ('PENDING', 'PROCESSING') ORDER BY tq.priority ASC, tq.createdAt ASC")
    List<TaskQueue> findPendingTasksByUsername(@Param("username") String username);

    /**
     * 统计用户待处理任务数量
     */
    @Query("SELECT COUNT(tq) FROM TaskQueue tq WHERE tq.username = :username AND tq.status IN ('PENDING', 'PROCESSING')")
    long countPendingTasksByUsername(@Param("username") String username);

    /**
     * 根据任务ID查找队列任务
     */
    Optional<TaskQueue> findByTaskId(String taskId);
    
    /**
     * 使用悲观锁查找任务（SELECT FOR UPDATE）
     * 用于防止并发处理同一任务
     */
    @Query("SELECT tq FROM TaskQueue tq WHERE tq.taskId = :taskId")
    @Lock(LockModeType.PESSIMISTIC_WRITE)
    Optional<TaskQueue> findByTaskIdWithLock(@Param("taskId") String taskId);

    /**
     * 根据用户名和任务ID查找队列任务
     */
    Optional<TaskQueue> findByUsernameAndTaskId(String username, String taskId);

    /**
     * 查找所有需要检查的任务（状态为PROCESSING且未超时）
     */
    @Query("SELECT tq FROM TaskQueue tq WHERE tq.status = 'PROCESSING' AND tq.checkCount < tq.maxCheckCount ORDER BY tq.lastCheckTime ASC NULLS FIRST, tq.createdAt ASC")
    List<TaskQueue> findTasksToCheck();
    
    /**
     * 统计需要检查的任务数量（状态为PROCESSING且未超时）
     * 用于快速检查是否有待处理任务
     */
    @Query("SELECT COUNT(tq) FROM TaskQueue tq WHERE tq.status = 'PROCESSING' AND tq.checkCount < tq.maxCheckCount")
    long countTasksToCheck();

    /**
     * 查找超时的任务
     */
    @Query("SELECT tq FROM TaskQueue tq WHERE tq.status = 'PROCESSING' AND tq.checkCount >= tq.maxCheckCount")
    List<TaskQueue> findTimeoutTasks();

    /**
     * 查找所有待处理的任务（按优先级排序）
     */
    @Query("SELECT tq FROM TaskQueue tq WHERE tq.status = 'PENDING' ORDER BY tq.priority ASC, tq.createdAt ASC")
    List<TaskQueue> findAllPendingTasks();

    /**
     * 根据用户名分页查询任务
     */
    @Query("SELECT tq FROM TaskQueue tq WHERE tq.username = :username ORDER BY tq.createdAt DESC")
    Page<TaskQueue> findByUsernameOrderByCreatedAtDesc(@Param("username") String username, Pageable pageable);

    /**
     * 统计用户总任务数
     */
    long countByUsername(String username);

    /**
     * 删除过期任务（超过7天）
     */
    @Modifying
    @Query("DELETE FROM TaskQueue tq WHERE tq.createdAt < :expiredDate")
    int deleteExpiredTasks(@Param("expiredDate") LocalDateTime expiredDate);

    /**
     * 更新任务状态
     */
    @Modifying
    @Query("UPDATE TaskQueue tq SET tq.status = :status, tq.updatedAt = :updatedAt, tq.completedAt = :completedAt WHERE tq.taskId = :taskId")
    int updateTaskStatus(@Param("taskId") String taskId, 
                        @Param("status") TaskQueue.QueueStatus status, 
                        @Param("updatedAt") LocalDateTime updatedAt,
                        @Param("completedAt") LocalDateTime completedAt);

    /**
     * 更新检查信息
     */
    @Modifying
    @Query("UPDATE TaskQueue tq SET tq.checkCount = tq.checkCount + 1, tq.lastCheckTime = :lastCheckTime, tq.updatedAt = :updatedAt WHERE tq.taskId = :taskId")
    int updateCheckInfo(@Param("taskId") String taskId, 
                       @Param("lastCheckTime") LocalDateTime lastCheckTime,
                       @Param("updatedAt") LocalDateTime updatedAt);

    /**
     * 更新真实任务ID
     */
    @Modifying
    @Query("UPDATE TaskQueue tq SET tq.realTaskId = :realTaskId, tq.updatedAt = :updatedAt WHERE tq.taskId = :taskId")
    int updateRealTaskId(@Param("taskId") String taskId, 
                        @Param("realTaskId") String realTaskId,
                        @Param("updatedAt") LocalDateTime updatedAt);

    /**
     * 更新错误信息
     */
    @Modifying
    @Query("UPDATE TaskQueue tq SET tq.errorMessage = :errorMessage, tq.updatedAt = :updatedAt WHERE tq.taskId = :taskId")
    int updateErrorMessage(@Param("taskId") String taskId, 
                          @Param("errorMessage") String errorMessage,
                          @Param("updatedAt") LocalDateTime updatedAt);

    /**
     * 根据状态查找任务
     */
    List<TaskQueue> findByStatus(TaskQueue.QueueStatus status);

    /**
     * 根据状态删除任务
     */
    @Modifying
    @Query("DELETE FROM TaskQueue tq WHERE tq.status = :status")
    int deleteByStatus(@Param("status") TaskQueue.QueueStatus status);

    /**
     * 根据状态统计任务数量
     */
    long countByStatus(TaskQueue.QueueStatus status);

    /**
     * 查找创建时间在指定时间之后的任务
     */
    List<TaskQueue> findByCreatedAtAfter(LocalDateTime dateTime);

    /**
     * 查找超时的任务（基于创建时间）
     * 状态为PENDING或PROCESSING，且创建时间早于指定时间
     */
    @Query("SELECT tq FROM TaskQueue tq WHERE tq.status IN ('PENDING', 'PROCESSING') AND tq.createdAt < :timeoutTime")
    List<TaskQueue> findTimeoutTasksByCreatedTime(@Param("timeoutTime") LocalDateTime timeoutTime);
}

