package com.sonic.lion.service.impl;

import com.sonic.lion.domain.entity.PayCharge;
import com.sonic.lion.domain.enums.SystemUser;
import com.sonic.lion.domain.input.PrePaymentInput;
import com.sonic.lion.domain.output.PrePaymentOutput;
import com.sonic.lion.domain.req.PreChargeReq;
import com.sonic.lion.domain.resp.PrePaymentResp;
import com.sonic.lion.enums.*;
import com.sonic.lion.service.*;
import com.sonic.lion.utils.LimitUtils;
import com.sonic.lion.utils.RedisKeyUtils;
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 java.math.BigDecimal;
import java.time.LocalDateTime;


@Slf4j
@Service
public class PreChargeHandlerServiceImpl implements PreChargeHandlerService {

    /**
     * 30分钟后关闭交易
     */
    private static final int CHARGE_PAYMENT_MINUTES = 30;


    @Value("${apple.paymentPlatformFeeRate}")
    private BigDecimal applePaymentPlatformFeeRate;
    @Value("${google.paymentPlatformFeeRate}")
    private BigDecimal googlePaymentPlatformFeeRate;

    @Autowired
    private RedisKeyUtils redisKeyUtils;
    @Autowired
    private LimitUtils limitUtils;
    @Autowired
    private PayTradeService payTradeService;
    @Autowired
    private AccountBuffService accountBuffService;
    @Autowired
    private GoogleService googleService;
    @Autowired
    private PayChargeService payChargeService;

    @Override
    public PrePaymentResp preCharge(Long userId, PreChargeReq req, String ip) {
        //限流处理
        Boolean bl = limitUtils.defaultLimitCheckByKey(redisKeyUtils.createPrePayTrade(userId), 100, 3600);
        ToastResultCode.SYSTEM_EXCEPTION.check(bl, "operate too frequently，please try again later (102)");
        //根据商品ID获取价格
        PayCharge payCharge = payChargeService.getByBundleIdAndProductIdAndPlatform(req.getProductId(), "web");
        ToastResultCode.DATA_NOT_EXITS.check(payCharge == null);
        long occurAmount = payCharge.getPayAmount();

        PrePaymentInput input = PrePaymentInput.builder()
                .platform(Platform.PAY.getDesc())
                .bizType(BizType.CHARGE)
                .name(BizType.CHARGE.getDesc())
                .srcAccountId(userId)
                .desAccountNo(String.valueOf(SystemUser.SYSTEM_USER_1.getValue()))
                .productAmount(payCharge.getPayAmount())
                .actualAmount(payCharge.getChargeAmount())
                .occurAmount(occurAmount)
                .srcAccountName("")
                .ip(ip)
                .productId(req.getProductId())
                .payChannel(PayChannel.STRIPE)
                .clientVersion(null)
                .closeTime(LocalDateTime.now().plusMinutes(CHARGE_PAYMENT_MINUTES))
                .build();

        PrePaymentOutput prePaymentOutput = payTradeService.prePayment(input);
        return PrePaymentResp.builder()
                .tradeNo(prePaymentOutput.getTradeNo())
                .tradeStatus(prePaymentOutput.getTradeStatus())
                .build();
    }

    @Override
    public PrePaymentResp iapPreCharge(Long userId, PreChargeReq req, String ip) {
        //限流处理
        Boolean bl = limitUtils.defaultLimitCheckByKey(redisKeyUtils.createPrePayTrade(userId), 100, 3600);
        ToastResultCode.SYSTEM_EXCEPTION.check(bl, "operate too frequently，please try again later (102)");

        PayCharge payCharge = payChargeService.getByBundleIdAndProductIdAndPlatform(req.getProductId(), "iOS");
        ToastResultCode.DATA_NOT_EXITS.check(payCharge == null);
        long occurAmount = payCharge.getPayAmount();
        //计算总的手续费
        long fee = googleService.calculatePaymentFee(payCharge);
        //计算平台抽成
        long platformFee = new BigDecimal(occurAmount + 1).multiply(applePaymentPlatformFeeRate).longValue() - 1;
        platformFee = platformFee > 0 ? platformFee : 0;
        //计算三方手续费
        long thirdFee = fee - platformFee;
        PrePaymentInput input = PrePaymentInput.builder()
                .platform(Platform.PAY.getDesc())
                .bizType(BizType.CHARGE)
                .name(BizType.CHARGE.getDesc())
                .srcAccountId(userId)
                .desAccountNo(String.valueOf(SystemUser.SYSTEM_USER_1.getValue()))
                .productAmount(payCharge.getPayAmount())
                .actualAmount(payCharge.getChargeAmount())
                .payChannel(PayChannel.IAP)
                .occurAmount(occurAmount)
                .fee(fee)
                .platformFee(platformFee)
                .thirdFee(thirdFee)
                .srcAccountName("")
                .paymentType(PaymentType.CHANNEL)
                .productId(req.getProductId())
                .clientVersion(null)
                .ip(ip)
                .build();
        PrePaymentOutput prePaymentOutput = payTradeService.prePayment(input);
        return PrePaymentResp.builder()
                .tradeNo(prePaymentOutput.getTradeNo())
                .tradeStatus(prePaymentOutput.getTradeStatus())
                .build();
    }

    @Override
    public PrePaymentResp googlePreCharge(Long userId, PreChargeReq req, String ip) {
        //限流处理
        Boolean bl = limitUtils.defaultLimitCheckByKey(redisKeyUtils.createPrePayTrade(userId), 100, 3600);
        ToastResultCode.SYSTEM_EXCEPTION.check(bl, "operate too frequently，please try again later (102)");
        //根据产品ID获取价格相关的数据
        PayCharge payCharge = payChargeService.getByBundleIdAndProductIdAndPlatform(req.getProductId(), "android");
        ToastResultCode.DATA_NOT_EXITS.check(payCharge == null);
        long occurAmount = payCharge.getPayAmount();
        //计算总的手续费
        long fee = googleService.calculatePaymentFee(payCharge);
        //计算平台抽成
        long platformFee = new BigDecimal(occurAmount + 1).multiply(googlePaymentPlatformFeeRate).longValue() - 1;
        platformFee = platformFee > 0 ? platformFee : 0;
        //计算三方手续费
        long thirdFee = fee - platformFee;
        PrePaymentInput input = PrePaymentInput.builder()
                .platform(Platform.PAY.getDesc())
                .bizType(BizType.CHARGE)
                .name(BizType.CHARGE.getDesc())
                .srcAccountId(userId)
                .desAccountNo(String.valueOf(SystemUser.SYSTEM_USER_1.getValue()))
                .productAmount(payCharge.getPayAmount())
                .actualAmount(payCharge.getChargeAmount())
                .payChannel(PayChannel.GOOGLE)
                .occurAmount(occurAmount)
                .fee(fee)
                .platformFee(platformFee)
                .thirdFee(thirdFee)
                .srcAccountName("")
                .paymentType(PaymentType.CHANNEL)
                .productId(req.getProductId())
                .clientVersion(null)
                .ip(ip)
                .build();
        PrePaymentOutput prePaymentOutput = payTradeService.prePayment(input);
        return PrePaymentResp.builder()
                .tradeNo(prePaymentOutput.getTradeNo())
                .tradeStatus(prePaymentOutput.getTradeStatus())
                .build();
    }

}
