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.GameTencentMiniGameOrder;
import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameOrderSplitLog;
import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
import com.zanxiang.game.back.serve.pojo.enums.BackTypeEnum;
import com.zanxiang.game.back.serve.service.IGameTencentMiniGameBackLogService;
import com.zanxiang.game.back.serve.service.IGameTencentMiniGameOrderService;
import com.zanxiang.game.back.serve.service.IGameTencentMiniGameOrderSplitLogService;
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 TencentMiniOrderSplitBackTask {
    public static final String KEY = ServerInfo.SERVER_NAME + ":tencentMiniOrderSplitBack:";

    @Autowired
    private IGameTencentMiniGameOrderService gameTencentMiniGameOrderService;

    @Autowired
    private IGameTencentMiniGameOrderSplitLogService gameTencentMiniGameOrderSplitLogService;

    @Autowired
    private IDistributedLockComponent distributedLockComponent;

    @Autowired
    private IGameTencentMiniGameBackLogService gameTencentMiniGameBackLogService;

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

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

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