package com.sonic.lion.service.impl;

import com.sonic.lion.dao.PayCallChannelRecordDao;
import com.sonic.lion.dao.ProcessingWithdrawDao;
import com.sonic.lion.domain.entity.PayCallChannelRecord;
import com.sonic.lion.domain.entity.ProcessingWithdraw;
import com.sonic.lion.domain.enums.CallChannelStatus;
import com.sonic.lion.domain.output.SyncChannelOutput;
import com.sonic.lion.service.ProcessingWithdrawService;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ProcessingWithdrawServiceImpl implements ProcessingWithdrawService {

    @Autowired
    private ProcessingWithdrawDao processingWithdrawDao;

    @Autowired
    private TradeHandler tradeHandler;


    @Autowired
    private PayCallChannelRecordDao payCallChannelRecordDao;

    /**
     * 最大增加的下次处理时间增加的分钟数
     */
    private static Integer MAX_NEXT_TIME = 60;

    /**
     * 处理次数和下次处理时间增加分钟数的映射关系
     */
    private static Map<Integer, Integer> HANDLER_COUNT_TIME_MAP = Maps.newHashMap();

    static {
        //key 处理次数，value 下次处理时间增加的分钟数
        HANDLER_COUNT_TIME_MAP.put(0, 1);
        HANDLER_COUNT_TIME_MAP.put(1, 1);
        HANDLER_COUNT_TIME_MAP.put(2, 3);
        HANDLER_COUNT_TIME_MAP.put(3, 5);
        HANDLER_COUNT_TIME_MAP.put(4, 10);
        HANDLER_COUNT_TIME_MAP.put(5, 15);
        HANDLER_COUNT_TIME_MAP.put(6, 20);
        HANDLER_COUNT_TIME_MAP.put(7, 25);
        HANDLER_COUNT_TIME_MAP.put(8, 30);
        HANDLER_COUNT_TIME_MAP.put(9, 60);
    }

    @Override
    public void hand() {
        //查询出下次处理时间小于当前时间的数据进行处理，每次最多查询50条数据进行处理
        List<ProcessingWithdraw> list = processingWithdrawDao.findAll();
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        log.info("handProcessingWithdraw size {}", list.size());
        List<PayCallChannelRecord> payCallChannelRecords = payCallChannelRecordDao.selectBatchIds(list.stream().map(ProcessingWithdraw::getCallChannelRecordId).collect(Collectors.toList()));
        Map<Long, PayCallChannelRecord> map = payCallChannelRecords.stream().collect(Collectors.toMap(PayCallChannelRecord::getId, record -> record));

        for (ProcessingWithdraw processingWithdraw : list) {
            hand(map, processingWithdraw);
        }
    }

    private void hand(Map<Long, PayCallChannelRecord> map, ProcessingWithdraw processingWithdraw) {
        try {
            PayCallChannelRecord payCallChannelRecord = map.get(processingWithdraw.getCallChannelRecordId());
            log.info("handProcessingWithdraw ing ....{}", payCallChannelRecord);

            //根据次数来增加时间
            Integer handCount = processingWithdraw.getHandCount() == null ? 0 : processingWithdraw.getHandCount() + 1;
            Integer addTimeSeconds = HANDLER_COUNT_TIME_MAP.get(handCount);
            if(addTimeSeconds == null) {
                addTimeSeconds = MAX_NEXT_TIME;
            }
            LocalDateTime nextHandTime = processingWithdraw.getNextHandTime() == null ?
                    LocalDateTime.now() : processingWithdraw.getNextHandTime().plusMinutes(addTimeSeconds);
            ProcessingWithdraw updateProcessingWithdraw = new ProcessingWithdraw();
            updateProcessingWithdraw.setId(processingWithdraw.getId());
            updateProcessingWithdraw.setNextHandTime(nextHandTime);
            updateProcessingWithdraw.setHandCount(handCount);
            processingWithdrawDao.updateById(updateProcessingWithdraw);

            //调用第三方查询确认转账交易的最终执行结果
            SyncChannelOutput syncChannelOutput  = tradeHandler.syncOrder(payCallChannelRecord);
            if(CallChannelStatus.PROCESSING.equals(syncChannelOutput.getCallChannelStatus()) || CallChannelStatus.INIT.equals(syncChannelOutput.getCallChannelStatus())){
                //状态为处理中或初始化则不做任何处理
            }else{
                //其余状态直接删除掉待处理数据
                processingWithdrawDao.deleteById(processingWithdraw.getId());
            }
        } catch (Exception e) {
            log.error("handProcessingWithdraw fail", e);
        }
    }
}
