package com.lesingle.modules.leai.task;

import com.lesingle.modules.leai.entity.LeaiWebhookEvent;
import com.lesingle.modules.leai.service.ILeaiSyncService;
import com.lesingle.modules.leai.service.ILeaiWebhookEventService;
import com.lesingle.modules.leai.service.LeaiApiClient;
import com.lesingle.modules.leai.util.LeaiUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

/**
 * 定时任务：B3 对账 + Webhook 失败重试
 * <p>
 * 1. B3 对账：开发/测试环境每 1 分钟，生产环境每 30 分钟（配置项 leai.reconcile-interval）
 * 2. 每 10 分钟重试失败的 Webhook 事件（最多 3 次）
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class LeaiReconcileTask {

    private final LeaiApiClient leaiApiClient;
    private final ILeaiSyncService leaiSyncService;
    private final ILeaiWebhookEventService webhookEventService;

    /** 最大重试次数 */
    private static final int MAX_RETRY_COUNT = 3;
    /** 每次重试查询条数 */
    private static final int RETRY_BATCH_SIZE = 20;

    /**
     * B3 定时对账
     * 间隔由 leai.reconcile-interval 配置（开发/测试: 1分钟，生产: 30分钟）
     */
    @Scheduled(fixedRateString = "${leai.reconcile-interval:1800000}", initialDelayString = "${leai.reconcile-initial-delay:60000}")
    public void reconcile() {
        log.info("[B3对账] 开始执行...");

        try {
            String updatedAfter = LeaiApiClient.getUtcTwoHoursAgoIso();

            List<Map<String, Object>> works = leaiApiClient.queryWorks(updatedAfter);
            if (works.isEmpty()) {
                log.info("[B3对账] 未查询到变更作品");
                return;
            }

            int synced = 0;
            int skipped = 0;
            for (Map<String, Object> work : works) {
                String workId = LeaiUtil.toString(work.get("workId"), null);
                if (workId == null) {
                    continue;
                }

                // 过滤无 phone 的旧测试数据
                String phone = LeaiUtil.toString(work.get("phone"), null);
                if (phone == null) {
                    log.debug("[B3对账] 跳过无phone数据: workId={}", workId);
                    skipped++;
                    continue;
                }

                Map<String, Object> fullData = leaiApiClient.fetchWorkDetail(workId);
                if (fullData != null) {
                    // B2 详情接口不返回 phone，将 B3 列表中的 phone 合并进去
                    fullData.put("phone", phone);
                    try {
                        leaiSyncService.syncWork(workId, fullData, "B3对账");
                        synced++;
                    } catch (Exception e) {
                        log.warn("[B3对账] 同步失败: workId={}", workId, e);
                    }
                } else {
                    try {
                        leaiSyncService.syncWork(workId, work, "B3对账(摘要)");
                        synced++;
                    } catch (Exception e) {
                        log.warn("[B3对账] 摘要同步失败: workId={}", workId, e);
                    }
                }
            }

            log.info("[B3对账] 完成: 检查 {} 个作品, 同步 {} 个, 跳过无phone {} 个", works.size(), synced, skipped);

        } catch (Exception e) {
            log.error("[B3对账] 执行异常", e);
        }
    }

    /**
     * Webhook 失败事件重试
     * 每 10 分钟执行，初始延迟 120 秒
     */
    @Scheduled(fixedRate = 10 * 60 * 1000, initialDelay = 120 * 1000)
    public void retryFailedEvents() {
        List<LeaiWebhookEvent> failedEvents = webhookEventService.findFailedEvents(MAX_RETRY_COUNT, RETRY_BATCH_SIZE);
        if (failedEvents.isEmpty()) {
            return;
        }

        log.info("[Webhook重试] 发现 {} 个失败事件待重试", failedEvents.size());

        int successCount = 0;
        int failCount = 0;
        for (LeaiWebhookEvent event : failedEvents) {
            String remoteWorkId = event.getRemoteWorkId();
            if (remoteWorkId == null || remoteWorkId.isEmpty()) {
                // 无作品ID的事件标记为已处理（无法重试）
                event.setProcessed(1);
                webhookEventService.updateById(event);
                continue;
            }

            try {
                // 尝试从远端重新拉取数据并同步
                Map<String, Object> fullData = leaiApiClient.fetchWorkDetail(remoteWorkId);
                if (fullData != null) {
                    leaiSyncService.syncWork(remoteWorkId, fullData, "Webhook重试");
                }
                // 同步成功，标记为已处理
                event.setProcessed(1);
                event.setRetryCount(event.getRetryCount() != null ? event.getRetryCount() + 1 : 1);
                webhookEventService.updateById(event);
                successCount++;
            } catch (Exception e) {
                // 重试失败，增加计数
                event.setRetryCount(event.getRetryCount() != null ? event.getRetryCount() + 1 : 1);
                event.setErrorMessage(e.getMessage());
                // 达到最大重试次数则放弃
                if (event.getRetryCount() >= MAX_RETRY_COUNT) {
                    event.setProcessed(3); // 3=彻底失败，不再重试
                    log.warn("[Webhook重试] 事件 {} 达到最大重试次数，放弃: remoteWorkId={}", event.getEventId(), remoteWorkId);
                }
                webhookEventService.updateById(event);
                failCount++;
            }
        }

        log.info("[Webhook重试] 完成: 成功 {}, 失败 {}", successCount, failCount);
    }
}
