package com.bizzan.bitrade.job;

import com.bizzan.bitrade.dao.CoinNetworkDao;
import com.bizzan.bitrade.entity.CoinNetwork;
import com.bizzan.bitrade.entity.CoinRechargeOrder;
import com.bizzan.bitrade.service.CoinRechargeConfirmService;
import com.bizzan.bitrade.service.CoinRechargeOrderService;
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.Map;
import java.util.stream.Collectors;

/**
 * 链上充值订单扫描定时任务
 * 每 1 分钟扫描一次 CONFIRMING 状态的充值订单，
 * 委托 CoinRechargeConfirmService 完成链上验证和入账
 *
 * @author auto
 * @date 2026-05-13
 */
@Slf4j
@Component
public class CoinRechargeOrderScanJob {

    @Autowired
    private CoinRechargeOrderService coinRechargeOrderService;

    @Autowired
    private CoinRechargeConfirmService coinRechargeConfirmService;

    @Autowired
    private CoinNetworkDao coinNetworkDao;

    /** PENDING 订单超时分钟数 */
    private static final int PENDING_EXPIRE_MINUTES = 5;

    /**
     * 每 1 分钟扫描一次待确认充值订单
     */
    @Scheduled(cron = "0 0/1 * * * ?")
    public void scanConfirmingOrders() {
        // 1. 查询所有待链上确认的订单
        List<CoinRechargeOrder> orders = coinRechargeOrderService.findAllConfirming();
        if (orders == null || orders.isEmpty()) {
            return;
        }
        log.info("[充值扫描] 本次扫描到 {} 笔待确认订单", orders.size());

        // 2. 批量加载主网配置，避免循环内重复查库
        Map<String, CoinNetwork> networkMap = coinNetworkDao.findAllByOrderBySortAsc()
                .stream()
                .collect(Collectors.toMap(CoinNetwork::getName, n -> n, (a, b) -> a));

        // 3. 逐笔委托 Service 处理（每笔独立事务，互不影响）
        for (CoinRechargeOrder order : orders) {
            try {
                CoinNetwork network = networkMap.get(order.getNetworkName());
                coinRechargeConfirmService.confirmOrder(order, network);
            } catch (Exception e) {
                log.error("[充值扫描] 处理订单异常, orderNo={}, error={}",
                        order.getOrderNo(), e.getMessage());
            }
        }
    }

    /**
     * 每 1 分钟扫描一次超时未支付的 PENDING 订单，超过 5 分钟未提交 hash 则自动取消
     */
    @Scheduled(cron = "0 */1 * * * ?")
    public void cancelExpiredPendingOrders() {
        // 1. 查询超时未支付订单
        List<CoinRechargeOrder> expiredOrders =
                coinRechargeOrderService.findAllPendingExpired(PENDING_EXPIRE_MINUTES);
        if (expiredOrders == null || expiredOrders.isEmpty()) {
            return;
        }
        log.info("[充值超时] 发现 {} 笔超时未支付订单，即将取消", expiredOrders.size());

        // 2. 逐笔取消（每笔独立事务，互不影响）
        for (CoinRechargeOrder order : expiredOrders) {
            try {
                coinRechargeOrderService.markCancelled(order, "超过 " + PENDING_EXPIRE_MINUTES + " 分钟未提交交易 hash，系统自动取消");
                log.info("[充值超时] 已取消超时订单，orderNo={}, memberId={}",
                        order.getOrderNo(), order.getMemberId());
            } catch (Exception e) {
                log.error("[充值超时] 取消订单异常, orderNo={}, error={}",
                        order.getOrderNo(), e.getMessage());
            }
        }
    }
}
