package com.nanri.aiimage.modules.deletebrand.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nanri.aiimage.config.DeleteBrandProgressProperties;
import com.nanri.aiimage.modules.task.mapper.FileTaskMapper;
import com.nanri.aiimage.modules.task.model.entity.FileTaskEntity;
import lombok.RequiredArgsConstructor;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Map;

@Service
@RequiredArgsConstructor
public class DeleteBrandStaleTaskService {

    private static final String MODULE_TYPE = "DELETE_BRAND";

    private final FileTaskMapper fileTaskMapper;
    private final DeleteBrandTaskCacheService deleteBrandTaskCacheService;
    private final DeleteBrandRunService deleteBrandRunService;
    private final DeleteBrandProgressProperties deleteBrandProgressProperties;

    @Scheduled(cron = "${aiimage.delete-brand-progress.stale-check-cron:0 */2 * * * *}")
    public void failStaleRunningTasks() {
        LocalDateTime threshold = LocalDateTime.now().minusMinutes(deleteBrandProgressProperties.getHeartbeatTimeoutMinutes());

        // 先按 DB updatedAt 粗筛，避免全表扫描
        java.util.List<FileTaskEntity> runningTasks = fileTaskMapper.selectList(new LambdaQueryWrapper<FileTaskEntity>()
                .eq(FileTaskEntity::getModuleType, MODULE_TYPE)
                .eq(FileTaskEntity::getStatus, "RUNNING")
                .lt(FileTaskEntity::getUpdatedAt, threshold)
                .last("limit 200"));

        for (FileTaskEntity task : runningTasks) {
            Map<Object, Object> progress = deleteBrandTaskCacheService.getProgress(task.getId());
            boolean hasProgress = progress != null && !progress.isEmpty() && progress.containsKey("last_heartbeat_at");

            boolean isActive = false;
            if (progress != null && progress.containsKey("has_progress")) {
                Object hpObj = progress.get("has_progress");
                if (hpObj instanceof Boolean) {
                    isActive = (Boolean) hpObj;
                } else if (hpObj instanceof String) {
                    isActive = Boolean.parseBoolean((String) hpObj);
                }
            }

            long lastHeartbeatAt = 0L;
            if (hasProgress) {
                try {
                    lastHeartbeatAt = Long.parseLong(String.valueOf(progress.get("last_heartbeat_at")));
                } catch (Exception ignored) {
                }
            }

            LocalDateTime lastActivityTime;
            // 只有当 has_progress 为 true 且超过 15 分钟没心跳，才认为是异常卡死
            if (lastHeartbeatAt > 0 && isActive) {
                // 有心跳，用最后心跳时间对比 15 分钟 (threshold 是 now - 15)
                lastActivityTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(lastHeartbeatAt), ZoneId.systemDefault());
                if (lastActivityTime.isAfter(threshold)) {
                    continue; // 没超时
                }
            } else {
                // 没有心跳，或者当前处在 has_progress: false （等待用户点击下一个任务推送的静默期）
                // 静默期和排队期的宽限期一样，设为 12 个小时
                LocalDateTime queuedThreshold = LocalDateTime.now().minusHours(12);
                if (task.getCreatedAt() != null && task.getCreatedAt().isAfter(queuedThreshold)) {
                    continue; // 等待下个队列推送中，不要杀它！
                }
            }

            int updated = fileTaskMapper.update(null, new com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper<FileTaskEntity>()
                    .eq(FileTaskEntity::getId, task.getId())
                    .eq(FileTaskEntity::getModuleType, MODULE_TYPE)
                    .eq(FileTaskEntity::getStatus, "RUNNING")
                    .set(FileTaskEntity::getStatus, "FAILED")
                    .set(FileTaskEntity::getErrorMessage, "结果回传长时间无响应，任务已自动失败")
                    .set(FileTaskEntity::getUpdatedAt, LocalDateTime.now())
                    .set(FileTaskEntity::getFinishedAt, LocalDateTime.now()));

            if (updated > 0) {
                deleteBrandTaskCacheService.delete(task.getId());
            }
        }
    }

    @Scheduled(cron = "${aiimage.delete-brand-progress.finalize-check-cron:30 */2 * * * *}")
    public void finalizeCompletedRunningTasks() {
        java.util.List<FileTaskEntity> runningTasks = fileTaskMapper.selectList(new LambdaQueryWrapper<FileTaskEntity>()
                .eq(FileTaskEntity::getModuleType, MODULE_TYPE)
                .eq(FileTaskEntity::getStatus, "RUNNING")
                .orderByAsc(FileTaskEntity::getUpdatedAt)
                .last("limit 100"));

        for (FileTaskEntity task : runningTasks) {
            try {
                deleteBrandRunService.tryFinalizeTask(task.getId(), true);
            } catch (Exception ignored) {
                // 定时补偿不影响主流程；下次调度或人工重试时再处理
            }
        }
    }
}
