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.GameTencentOrder;
import com.zanxiang.game.back.serve.pojo.entity.GameTencentOrderSplitLog;
import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
import com.zanxiang.game.back.serve.service.IGameTencentOrderService;
import com.zanxiang.game.back.serve.service.IGameTencentOrderSplitLogService;
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 TencentOrderSplitBackTask {
    public static final String KEY = ServerInfo.SERVER_NAME + ":tencentOrderSplitBack:";

    @Autowired
    private IGameTencentOrderService gameTencentOrderService;
    @Autowired
    private IGameTencentOrderSplitLogService gameTencentOrderSplitLogService;

    @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<GameTencentOrderSplitLog> orderSplitLogList = gameTencentOrderSplitLogService.list(new LambdaQueryWrapper<GameTencentOrderSplitLog>()
                .in(GameTencentOrderSplitLog::getBackDay, Arrays.asList(LocalDate.now().minusDays(1), LocalDate.now()))
                .lt(GameTencentOrderSplitLog::getBackTime, now.plusMinutes(1))
                .eq(GameTencentOrderSplitLog::getBackStatus, BackStatusEnum.NO.getBackStatus())
                .orderByAsc(GameTencentOrderSplitLog::getOrderNo)
                .orderByAsc(GameTencentOrderSplitLog::getBackTime)
        );
        if (CollectionUtils.isEmpty(orderSplitLogList)) {
            return;
        }
        log.error("准备回传分拆订单：{}", orderSplitLogList.size());
        List<GameTencentOrder> orderList = gameTencentOrderService.list(new LambdaQueryWrapper<GameTencentOrder>()
                .in(GameTencentOrder::getOrderId, orderSplitLogList.stream().map(GameTencentOrderSplitLog::getOrderNo).collect(Collectors.toSet()))
        );
        Map<String, GameTencentOrder> 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(GameTencentOrder order, GameTencentOrderSplitLog orderSplitLog) {
        log.error("开始回传拆分订单：{}-{}", orderSplitLog.getOrderNo(), orderSplitLog.getBackIndex());
        try {
            Tuple2<BackStatusEnum, String> backResult = gameTencentOrderService.doCallback(order, orderSplitLog.getBackTime(), orderSplitLog.getSplitMoney());
            gameTencentOrderSplitLogService.update(new LambdaUpdateWrapper<GameTencentOrderSplitLog>()
                    .set(GameTencentOrderSplitLog::getExecuteTime, LocalDateTime.now())
                    .set(GameTencentOrderSplitLog::getBackStatus, backResult.first.getBackStatus())
                    .set(GameTencentOrderSplitLog::getBackErrorMsg, backResult.second)
                    .eq(GameTencentOrderSplitLog::getId, orderSplitLog.getId())
            );
            if (backResult.first == BackStatusEnum.SUCCESS) {
                gameTencentOrderService.update(new LambdaUpdateWrapper<GameTencentOrder>()
                        .set(GameTencentOrder::getIsBack, backResult.first.getBackStatus())
                        .eq(GameTencentOrder::getId, order.getId())
                );
            } else {
                gameTencentOrderService.update(new LambdaUpdateWrapper<GameTencentOrder>()
                        .set(GameTencentOrder::getIsBack, BackStatusEnum.SUCCESS_PART.getBackStatus())
                        .eq(GameTencentOrder::getId, order.getId())
                );
            }
            log.error("订单回传完成：{}-{}, {}-{}", orderSplitLog.getOrderNo(), orderSplitLog.getBackIndex(), backResult.first, backResult.second);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            try {
                gameTencentOrderSplitLogService.update(new LambdaUpdateWrapper<GameTencentOrderSplitLog>()
                        .set(GameTencentOrderSplitLog::getExecuteTime, LocalDateTime.now())
                        .set(GameTencentOrderSplitLog::getBackStatus, BackStatusEnum.FAILED.getBackStatus())
                        .set(GameTencentOrderSplitLog::getBackErrorMsg, e.getMessage())
                        .eq(GameTencentOrderSplitLog::getId, orderSplitLog.getId())
                );
                gameTencentOrderService.update(new LambdaUpdateWrapper<GameTencentOrder>()
                        .set(GameTencentOrder::getIsBack, BackStatusEnum.SUCCESS_PART.getBackStatus())
                        .eq(GameTencentOrder::getId, order.getId())
                );
            } catch (Exception ex) {
                log.error(ex.getMessage(), ex);
            }
        }
    }
}
