package com.spot.job;

import com.spot.entity.Account;
import com.spot.service.AccountService;
import com.spot.utils.Constant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 孤悬冻结余额释放定时任务
 * <p>
 * 每分钟扫描一次现货账户表，查找"有冻结余额但无对应活跃委托"的账户，
 * 将其 cold_money 全量归还到 hot_money，并在 account_record 中记录解冻流水。
 * <p>
 * 并发保护：使用 {@link AtomicBoolean} 标识当前是否有任务正在执行，
 * 若上一次任务未完成则跳过本次触发，避免重复执行。
 *
 * @author jean
 * @date 2026-05-08
 */
@Slf4j
@Component
public class ReleaseOrphanFrozenJob {

    @Autowired
    private AccountService accountService;

    /** 任务执行标志，true=正在执行，false=空闲 */
    private static final AtomicBoolean RUNNING = new AtomicBoolean(false);

    /**
     * 每分钟执行一次孤悬冻结检查与释放
     * fixedDelay 保证上一次执行完成后再等待 1 分钟才触发下一次
     */
    @Scheduled(fixedDelay = Constant.RELEASE_ORPHAN_FROZEN_INTERVAL_MS)
    public void execute() {
        // 若任务正在执行则跳过本次触发
        if (!RUNNING.compareAndSet(false, true)) {
            log.info("孤悬冻结释放任务正在执行中，跳过本次触发");
            return;
        }

        log.info("========== 开始执行孤悬冻结余额释放任务 ==========");
        int successCount = 0;
        int skipCount = 0;
        int failCount = 0;

        try {
            // 1. 批量查询有冻结余额但无活跃委托的账户
            List<Account> orphanAccounts =
                    accountService.findFrozenAccountsWithoutOrders(Constant.RELEASE_ORPHAN_FROZEN_BATCH_SIZE);

            if (orphanAccounts == null || orphanAccounts.isEmpty()) {
                log.debug("未发现孤悬冻结账户，任务结束");
                return;
            }

            log.info("发现 {} 个孤悬冻结账户，开始逐笔释放", orphanAccounts.size());

            // 2. 逐账户释放：每笔在独立事务内完成，互不干扰
            for (Account account : orphanAccounts) {
                // 二次校验：cold_money 若已为 0 则跳过（查询到释放之间的并发变化）
                if (account.getColdMoney() == null
                        || account.getColdMoney().compareTo(java.math.BigDecimal.ZERO) <= 0) {
                    skipCount++;
                    continue;
                }

                try {
                    accountService.releaseOrphanFrozenBalance(account);
                    successCount++;
                    log.info("孤悬冻结释放成功 - accountId={}, uid={}, symbol={}, coldMoney={}",
                            account.getId(), account.getUid(),
                            account.getSymbol(), account.getColdMoney());
                } catch (Exception e) {
                    failCount++;
                    log.error("孤悬冻结释放失败 - accountId={}, uid={}, symbol={}, coldMoney={}",
                            account.getId(), account.getUid(),
                            account.getSymbol(), account.getColdMoney(), e);
                }
            }

        } catch (Exception e) {
            log.error("孤悬冻结释放任务执行异常", e);
        } finally {
            // 无论成功与否，必须释放执行标志
            RUNNING.set(false);
            log.info("========== 孤悬冻结释放任务完成 - 成功:{}, 跳过:{}, 失败:{} ==========",
                    successCount, skipCount, failCount);
        }
    }
}
