package com.zanxiang.game.platform.serve.task;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.zanxiang.game.platform.serve.enums.GamePlatformEnum;
import com.zanxiang.game.platform.serve.exception.UnsupportedException;
import com.zanxiang.game.platform.serve.service.platform.PlatformBaseService;
import com.zanxiang.game.platform.serve.utils.SpringUtils;
import com.zanxiang.module.redis.service.IDistributedLockComponent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author : lingfeng
 * @time : 2021-08-03
 * @description : 同步书城订单信息
 */
@Slf4j
@Component
@RefreshScope
public class SyncPlatformOrderTask {

    private static final String LOCK_SYNC_ORDER_ROLLBACK = "platform:lockSyncOrderRollback";

    @Autowired
    private IDistributedLockComponent distributedLockComponent;

    @Value("${sys-config.task_is_run}")
    private boolean run;

    /**
     * 线程池
     */
    private static final ExecutorService THREAD_POOL_EARLY_MORNING = new ThreadPoolExecutor(
            3,
            3,
            0,
            TimeUnit.MINUTES,
            new LinkedBlockingQueue<>(),
            new ThreadFactoryBuilder()
                    .setNameFormat("async-order-early-morning-%d").build());

    /**
     * 每天凌晨 2点回滚前 10天的数据
     */
    @Scheduled(cron = "0 0 2 * * ?")
    public void rollback() {
        if (!run) {
            return;
        }
        long begin = System.currentTimeMillis();
        LocalDateTime endTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
        LocalDateTime startTime = endTime.minusDays(10);
        for (GamePlatformEnum gamePlatformEnum : GamePlatformEnum.values()) {
            if (gamePlatformEnum.getClazz() == null) {
                continue;
            }
            THREAD_POOL_EARLY_MORNING.execute(() -> {
                if (!distributedLockComponent.doLock(LOCK_SYNC_ORDER_ROLLBACK + "_" + gamePlatformEnum.getPlatformKey(), 0L, 12L, TimeUnit.HOURS)) {
                    return;
                }
                long start = System.currentTimeMillis();
                execute(gamePlatformEnum, startTime, endTime);
                long end = System.currentTimeMillis();
                if (end - begin > 60 * 60 * 1000) {
                    log.error("游戏平台【{}】同步订单(两点回滚)完成, 用时：{}, 调度用时：{}", gamePlatformEnum.getPlatformName(), (end - start) / 1000, (end - begin) / 1000);
                }
            });
        }
    }

    /**
     * 订单同步执行
     *
     * @param gamePlatformEnum 游戏平台枚举
     * @param startTime        开始时间
     * @param endTime          结束时间
     */
    private void execute(GamePlatformEnum gamePlatformEnum, LocalDateTime startTime, LocalDateTime endTime) {
        try {
            PlatformBaseService service = SpringUtils.getBean(gamePlatformEnum.getClazz());
            service.syncPlatformOrder(null, startTime, endTime);
        } catch (UnsupportedException ignored) {
        } catch (Exception e) {
            log.error("同步游戏平台【{}】的订单异常, 异常原因: {}", gamePlatformEnum.getPlatformName(), e.getMessage(), e);
        }
    }
}
