package com.yaoai.pipeline.async;

import com.yaoai.domain.entity.AiTask;
import com.yaoai.domain.mapper.AiTaskMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

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

/**
 * 定时扫描所有未到终态的视频任务并查询 Ark 状态。
 * 取代之前 {@link VideoTaskAsyncProcessor} 中阻塞 10 分钟的 in-thread 轮询：
 * - 不再占用 @Async 线程池
 * - 服务重启后自动 picked up 未完成的任务
 * - 硬性超时改为基于 created_at 的 30 分钟阈值
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class VideoTaskPoller {

    /** 单轮处理上限，防止 Ark 接口短时被打爆 */
    private static final int BATCH_LIMIT = 50;

    /** 任务从创建到必须终态的最大允许时长 */
    private static final Duration HARD_TIMEOUT = Duration.ofMinutes(30);

    private final AiTaskMapper aiTaskMapper;
    private final VideoTaskCompletionService completionService;

    @Scheduled(fixedDelayString = "${yaoai.video.poll-interval-ms:10000}", initialDelay = 10_000)
    public void poll() {
        List<AiTask> pending;
        try {
            pending = aiTaskMapper.findPollableVideoTasks(BATCH_LIMIT);
        } catch (Exception e) {
            log.error("Load pollable video tasks failed", e);
            return;
        }
        if (pending.isEmpty()) return;

        log.debug("Polling {} pending video task(s)", pending.size());
        LocalDateTime deadline = LocalDateTime.now().minus(HARD_TIMEOUT);

        for (AiTask task : pending) {
            // 硬超时兜底：避免 Ark 永不返回时任务永远停留在 submitted/running
            if (task.getCreatedAt() != null && task.getCreatedAt().isBefore(deadline)) {
                AiTask timeout = new AiTask();
                timeout.setId(task.getId());
                timeout.setStatus("failed");
                timeout.setErrorMessage("视频生成超时（超过 " + HARD_TIMEOUT.toMinutes() + " 分钟）");
                aiTaskMapper.updateById(timeout);
                log.warn("Video task hard-timeout: taskId={}, createdAt={}", task.getId(), task.getCreatedAt());
                continue;
            }
            completionService.pollOnce(task);
        }
    }
}
