package com.sonic.lion.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sonic.common.utils.MessageUtils;
import com.sonic.lion.domain.req.FreeWithdrawReq;
import com.sonic.lion.enums.FreeWithdrawReason;
import com.sonic.lion.enums.PayChannel;
import com.sonic.lion.dao.FreeWithdrawConfigDao;
import com.sonic.lion.dao.FreeWithdrawFeeBillDao;
import com.sonic.lion.domain.entity.FreeWithdrawConfig;
import com.sonic.lion.domain.entity.FreeWithdrawFeeBill;
import com.sonic.lion.domain.entity.PayTrade;
import com.sonic.lion.domain.input.WithdrawFeeInput;
import com.sonic.lion.domain.output.WithdrawFeeReduceInfoOutput;
import com.sonic.lion.service.FreeWithdrawConfigService;
import com.sonic.lion.service.PayAccountFundThirdService;
import com.sonic.lion.service.PayConfigService;
import com.sonic.lion.enums.ToastResultCode;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class FreeWithdrawConfigServiceImpl implements FreeWithdrawConfigService {

    @Value("${stripe.withdrawFeeBase:25}")
    private Long stripeWithdrawFeeBase;

    @Value("${stripe.withdrawFeeRate}")
    private BigDecimal stripeWithdrawFeeRate;

    @Autowired
    private FreeWithdrawConfigDao freeWithdrawConfigDao;

    @Autowired
    private PayAccountFundThirdService payAccountFundThirdService;

    @Autowired
    private FreeWithdrawFeeBillDao freeWithdrawFeeBillDao;
    @Autowired
    private PayConfigService payConfigService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void setFreeWithdraw(FreeWithdrawReq freeWithdraw) {
        FreeWithdrawConfig freeWithdrawConfig = freeWithdrawConfigDao.selectOne(Wrappers.<FreeWithdrawConfig>lambdaQuery().
                eq(FreeWithdrawConfig::getReason, freeWithdraw.getReason()).
                eq(FreeWithdrawConfig::getUid, freeWithdraw.getUid()));
        if (freeWithdrawConfig == null) {
            freeWithdrawConfig = FreeWithdrawConfig.builder()
                    .uid(freeWithdraw.getUid())
                    .startTime(freeWithdraw.getStartTime())
                    .endTime(freeWithdraw.getEndTime())
                    .reason(freeWithdraw.getReason())
                    .rate(freeWithdraw.getRate())
                    .createTime(LocalDateTime.now())
                    .editTime(LocalDateTime.now()).build();
            //只有开始时间不为空时才能够写入数据
            if(freeWithdrawConfig.getStartTime() != null) {
                freeWithdrawConfigDao.insert(freeWithdrawConfig);
            }
        } else {
            freeWithdrawConfig.setReason(freeWithdraw.getReason());
            freeWithdrawConfig.setStartTime(freeWithdraw.getStartTime() == null ? freeWithdrawConfig.getStartTime() : freeWithdraw.getStartTime());
            freeWithdrawConfig.setEndTime(freeWithdraw.getEndTime());
            freeWithdrawConfig.setEditTime(LocalDateTime.now());
            freeWithdrawConfig.setIsDelete(freeWithdraw.getIsDelete());
            freeWithdrawConfig.setRate(freeWithdraw.getRate());
            freeWithdrawConfigDao.updateById(freeWithdrawConfig);
        }
    }

    @Override
    public FreeWithdrawConfig isFree(Long uid, LocalDateTime withdrawRequestTime) {
        List<FreeWithdrawConfig> freeWithdrawConfigList = freeWithdrawConfigDao.listOrderByEndTime(uid);
        if (CollectionUtils.isEmpty(freeWithdrawConfigList)) {
            return null;
        }
        FreeWithdrawConfig result = null;
        for (FreeWithdrawConfig freeWithdrawConfig : freeWithdrawConfigList) {
            if (freeWithdrawConfig.getEndTime() == null) {
                if (withdrawRequestTime.isAfter(freeWithdrawConfig.getStartTime())) {
                    return freeWithdrawConfig;
                }
            } else {
                if (withdrawRequestTime.isAfter(freeWithdrawConfig.getStartTime()) && withdrawRequestTime.isBefore(freeWithdrawConfig.getEndTime())) {
                    return freeWithdrawConfig;
                }
            }
        }
        return result;
    }


    /**
     * 获取所有 免费的用户 ID
     *
     * @return
     */
    @Override
    public List<Long> getAllFreeUserIds() {
        List<Long> userIds = Lists.newArrayList();
        List<FreeWithdrawConfig> freeWithdrawConfigList = freeWithdrawConfigDao.selectList(Wrappers.<FreeWithdrawConfig>lambdaQuery()
                .eq(FreeWithdrawConfig::getIsDelete, Boolean.FALSE)
                .eq(FreeWithdrawConfig::getReason, FreeWithdrawReason.ANGEL_USER));

        userIds.addAll(freeWithdrawConfigList.stream().map(FreeWithdrawConfig::getUid).collect(Collectors.toList()));

        List<FreeWithdrawConfig> freeWithdrawConfigList2 = freeWithdrawConfigDao.selectList(Wrappers.<FreeWithdrawConfig>lambdaQuery()
                .eq(FreeWithdrawConfig::getIsDelete, Boolean.FALSE)
                .lt(FreeWithdrawConfig::getStartTime, LocalDateTime.now())
                .gt(FreeWithdrawConfig::getEndTime, LocalDateTime.now())
                .in(FreeWithdrawConfig::getReason, FreeWithdrawReason.SHOP_LEVEL, FreeWithdrawReason.OPERATION));

        userIds.addAll(freeWithdrawConfigList2.stream().map(FreeWithdrawConfig::getUid).collect(Collectors.toList()));
        return userIds;
    }


    @Override
    public FreeWithdrawConfig getFreeReson(Long uid) {
        List<FreeWithdrawConfig> freeWithdrawConfigList = freeWithdrawConfigDao.listOrderByEndTime(uid);
        if (CollectionUtils.isEmpty(freeWithdrawConfigList)) {
            return null;
        }
        FreeWithdrawConfig result = null;
        for (FreeWithdrawConfig freeWithdrawConfig : freeWithdrawConfigList) {
            if (freeWithdrawConfig.getEndTime() == null) {
                if (LocalDateTime.now().isAfter(freeWithdrawConfig.getStartTime())) {
                    return freeWithdrawConfig;
                }
            } else {
                if (LocalDateTime.now().isAfter(freeWithdrawConfig.getStartTime()) && LocalDateTime.now().isBefore(freeWithdrawConfig.getEndTime())) {
                    return freeWithdrawConfig;
                }
            }
        }
        return null;
    }

    @Override
    public WithdrawFeeInput calculateWithdrawFee(PayTrade payTrade) {
        WithdrawFeeInput withdrawFeeInput = new WithdrawFeeInput();
        //获取当天的 免手续费配置
        FreeWithdrawConfig freeWithdrawConfig = this.isFree(payTrade.getSrcAccountId(), payTrade.getCreateTime());
        //如果不为空 就免手续费 并且 新增免手续费记录表
        BigDecimal reduceRate = BigDecimal.ZERO;
        if (freeWithdrawConfig != null) {
            //减免比例
            reduceRate = freeWithdrawConfig.getRate();
            //如果减免原因是SHOP_LEVEL,则需要检查下开关是否开了，减免时间是否到期
            if (FreeWithdrawReason.SHOP_LEVEL.equals(freeWithdrawConfig.getReason())) {
                boolean enableEstar2WithdrawFeeReduction = payConfigService.enableWithdrawFeeReduction();
                //开关没开，不减免
                if (!enableEstar2WithdrawFeeReduction) {
                    reduceRate = BigDecimal.ZERO;
                }
                //超过了配置的时间，不减免
                LocalDateTime estar2WithdrawFeeReductionEndTime = payConfigService.withdrawFeeReductionEndTime();
                if (estar2WithdrawFeeReductionEndTime != null && LocalDateTime.now().isAfter(estar2WithdrawFeeReductionEndTime)) {
                    reduceRate = BigDecimal.ZERO;
                }
            }
        }

        if (reduceRate.compareTo(BigDecimal.ZERO) > 0) {
            //说明减免,新增免手续费记录表
            FreeWithdrawFeeBill freeWithdrawFeeBill = FreeWithdrawFeeBill.builder()
                    .uid(payTrade.getSrcAccountId())
                    .tradeNo(payTrade.getTradeNo())
                    .freeConfigId(freeWithdrawConfig.getId())
                    .reason(freeWithdrawConfig.getReason())
                    .editTime(LocalDateTime.now())
                    .deleted(Boolean.FALSE)
                    .createTime(LocalDateTime.now()).build();
            freeWithdrawFeeBillDao.insert(freeWithdrawFeeBill);
            withdrawFeeInput.setFreeWithdrawBillId(freeWithdrawFeeBill.getId());
        }

        //V6.12.0 平台默认收取10% 根据减免配置，收取一定的平台费用，6.19.1 版本调整成 20%
        BigDecimal platfromFeeRate = new BigDecimal(stripeWithdrawFeeRate.doubleValue());
        withdrawFeeInput.setPlatformFee(calcPlatformFee(platfromFeeRate.subtract(reduceRate), payTrade.getOccurAmount()));
        withdrawFeeInput.setThirdFee(getThirdWithdrawFee(payTrade, true));
        withdrawFeeInput.setWithdrawFee(withdrawFeeInput.getPlatformFee() + withdrawFeeInput.getThirdFee());
        return withdrawFeeInput;
    }

    /**
     * 计算平台收取费用
     *
     * @param rate
     * @param occurAmount
     * @return
     */
    private Long calcPlatformFee(BigDecimal rate, Long occurAmount) {
        //处理精度丢失的问题，只保留小数点后两位 (0.200000000000000011102230246251565404236316680908203125)
        rate = rate.setScale(2, BigDecimal.ROUND_DOWN);
        log.info("===> calcPlatformFee rate : {}, occurAmount : {}", rate, occurAmount);
        return rate.multiply(new BigDecimal(occurAmount)).setScale(0, BigDecimal.ROUND_UP).longValue();
    }

    private Long getThirdWithdrawFee(PayTrade payTrade, Boolean free) {
        if (payTrade.getPayChannel().equals(PayChannel.STRIPE)) {
            //手续费默认为 25L;
            return stripeWithdrawFeeBase;
        } else {
            ToastResultCode.UNSUPPORTED_BUSINESS_TYPE.check(true);
        }
        return 0L;
    }


    @Override
    public WithdrawFeeReduceInfoOutput getWithdrawFeeReduceInfo(Long userId) {
        WithdrawFeeReduceInfoOutput output = new WithdrawFeeReduceInfoOutput();
        FreeWithdrawConfig freeWithdrawConfig = getFreeReson(userId);
        if (freeWithdrawConfig == null) {
            output.setIsWithdrawFeeReduce(false);
            return output;
        }
        //SHOP_LEVEL类型
        if (FreeWithdrawReason.SHOP_LEVEL.equals(freeWithdrawConfig.getReason())) {
            Boolean isWithdrawFeeReduction = true;
            boolean enableEstar2WithdrawFeeReduction = payConfigService.enableWithdrawFeeReduction();
            //开关没开，不减免
            if (!enableEstar2WithdrawFeeReduction) {
                isWithdrawFeeReduction = false;
            }
            //超过了配置的时间，不减免
            LocalDateTime estar2WithdrawFeeReductionEndTime = payConfigService.withdrawFeeReductionEndTime();
            if (estar2WithdrawFeeReductionEndTime != null && LocalDateTime.now().isAfter(estar2WithdrawFeeReductionEndTime)) {
                isWithdrawFeeReduction = false;
            }
            if (!isWithdrawFeeReduction) {
                output.setIsWithdrawFeeReduce(false);
                return output;
            }
        }
        output.setIsWithdrawFeeReduce(true);
        output.setFreeWithdrawReason(freeWithdrawConfig.getReason());
        output.setReduceRate(freeWithdrawConfig.getRate());
        String text = MessageUtils.get(freeWithdrawConfig.getReason().name());
        String rate = freeWithdrawConfig.getRate().multiply(BigDecimal.valueOf(100)).toString();
        output.setTip(String.format(text, rate + "%"));
        return output;
    }

}



