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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.sd4324530.jtuple.Tuple2;
import com.zanxiang.game.back.base.ServerInfo;
import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineOrderLog;
import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineOrderSplitLog;
import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
import com.zanxiang.game.back.serve.service.IGameOceanengineOrderLogService;
import com.zanxiang.game.back.serve.service.IGameOceanengineOrderSplitLogService;
import com.zanxiang.module.redis.service.IDistributedLockComponent;
import com.zanxiang.module.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 头条订单拆分回传任务
 */
@Slf4j
@Component
public class OceanengineOrderSplitBackTask {
    public static final String KEY = ServerInfo.SERVER_NAME + ":oceanengineOrderSplitBack:";

    @Autowired
    private IGameOceanengineOrderLogService gameOceanengineOrderLogService;
    @Autowired
    private IGameOceanengineOrderSplitLogService gameOceanengineOrderSplitLogService;

    @Autowired
    private IDistributedLockComponent distributedLockComponent;

    @Scheduled(cron = "0 * * * * ?")
    public void execute() {
        LocalDateTime now = LocalDateTime.now().withSecond(0).withNano(0);
        if (!distributedLockComponent.doLock(KEY + DateUtil.formatLocalDateTime(now))) {
            return;
        }
        List<GameOceanengineOrderSplitLog> orderSplitLogList = gameOceanengineOrderSplitLogService.list(new LambdaQueryWrapper<GameOceanengineOrderSplitLog>()
                .in(GameOceanengineOrderSplitLog::getBackDay, Arrays.asList(LocalDate.now().minusDays(1), LocalDate.now()))
                .lt(GameOceanengineOrderSplitLog::getBackTime, now.plusMinutes(1))
                .eq(GameOceanengineOrderSplitLog::getBackStatus, BackStatusEnum.NO.getBackStatus())
                .orderByAsc(GameOceanengineOrderSplitLog::getOrderNo)
                .orderByAsc(GameOceanengineOrderSplitLog::getBackTime)
        );
        if (CollectionUtils.isEmpty(orderSplitLogList)) {
            return;
        }
        log.error("准备回传分拆订单：{}", orderSplitLogList.size());
        List<GameOceanengineOrderLog> orderList = gameOceanengineOrderLogService.list(new LambdaQueryWrapper<GameOceanengineOrderLog>()
                .in(GameOceanengineOrderLog::getOrderNo, orderSplitLogList.stream().map(GameOceanengineOrderSplitLog::getOrderNo).collect(Collectors.toSet()))
        );
        Map<String, GameOceanengineOrderLog> orderMap = new HashMap<>(orderList.size());
        orderList.forEach(order -> orderMap.put(order.getOrderNo(), order));

        orderSplitLogList.forEach(orderSplitLog -> {
            callback(orderMap.get(orderSplitLog.getOrderNo()), orderSplitLog);
        });
    }

    private void callback(GameOceanengineOrderLog order, GameOceanengineOrderSplitLog orderSplitLog) {
        log.error("开始回传拆分订单：{}-{}", orderSplitLog.getOrderNo(), orderSplitLog.getBackIndex());
        try {
            Tuple2<BackStatusEnum, String> backResult = gameOceanengineOrderLogService.doCallback(order, orderSplitLog.getBackTime(), orderSplitLog.getSplitMoney());
            gameOceanengineOrderSplitLogService.update(new LambdaUpdateWrapper<GameOceanengineOrderSplitLog>()
                    .set(GameOceanengineOrderSplitLog::getExecuteTime, LocalDateTime.now())
                    .set(GameOceanengineOrderSplitLog::getBackStatus, backResult.first.getBackStatus())
                    .set(GameOceanengineOrderSplitLog::getBackErrorMsg, backResult.second)
                    .eq(GameOceanengineOrderSplitLog::getId, orderSplitLog.getId())
            );
            if (backResult.first == BackStatusEnum.SUCCESS) {
                gameOceanengineOrderLogService.update(new LambdaUpdateWrapper<GameOceanengineOrderLog>()
                        .set(GameOceanengineOrderLog::getBackStatus, backResult.first.getBackStatus())
                        .eq(GameOceanengineOrderLog::getId, order.getId())
                );
            } else {
                gameOceanengineOrderLogService.update(new LambdaUpdateWrapper<GameOceanengineOrderLog>()
                        .set(GameOceanengineOrderLog::getBackStatus, BackStatusEnum.SUCCESS_PART.getBackStatus())
                        .eq(GameOceanengineOrderLog::getId, order.getId())
                );
            }
            log.error("订单回传完成：{}-{}, {}-{}", orderSplitLog.getOrderNo(), orderSplitLog.getBackIndex(), backResult.first, backResult.second);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            try {
                gameOceanengineOrderSplitLogService.update(new LambdaUpdateWrapper<GameOceanengineOrderSplitLog>()
                        .set(GameOceanengineOrderSplitLog::getExecuteTime, LocalDateTime.now())
                        .set(GameOceanengineOrderSplitLog::getBackStatus, BackStatusEnum.FAILED.getBackStatus())
                        .set(GameOceanengineOrderSplitLog::getBackErrorMsg, e.getMessage())
                        .eq(GameOceanengineOrderSplitLog::getId, orderSplitLog.getId())
                );
                gameOceanengineOrderLogService.update(new LambdaUpdateWrapper<GameOceanengineOrderLog>()
                        .set(GameOceanengineOrderLog::getBackStatus, BackStatusEnum.SUCCESS_PART.getBackStatus())
                        .eq(GameOceanengineOrderLog::getId, order.getId())
                );
            } catch (Exception ex) {
                log.error(ex.getMessage(), ex);
            }
        }
    }
}
