package org.springblade.yeePay.listener;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.constant.SystemConstant;
import org.springblade.common.utils.MoneyDesUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.guosen.bonusgroupbill.entity.BonusGroupBill;
import org.springblade.modules.guosen.bonusgroupbill.service.IBonusGroupBillService;
import org.springblade.modules.guosen.bussiness.entity.Bussiness;
import org.springblade.modules.guosen.bussiness.entity.BussinessDebit;
import org.springblade.modules.guosen.bussiness.service.IBussinessDebitService;
import org.springblade.modules.guosen.bussiness.service.IBussinessService;
import org.springblade.modules.guosen.bussinesspayorder.entity.BussinessPayOrder;
import org.springblade.modules.guosen.bussinesspayorder.service.IBussinessPayOrderService;
import org.springblade.modules.guosen.debtDaliyStat.entity.BusinessDeptDaliyStat;
import org.springblade.modules.guosen.debtDaliyStat.service.IBusinessDeptDaliyStatService;
import org.springblade.yeePay.entity.NotifyDto;
import org.springblade.yeePay.event.PayOrderNotifyEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.net.URI;
import java.util.Arrays;

@Component
@Slf4j
public class PayOrderNotifyListener {

    @Autowired
    private IBussinessDebitService bussinessDebitService;
    @Autowired
    private IBussinessService bussinessService;
    @Autowired
    private IBusinessDeptDaliyStatService businessDeptDailyStatService;
    @Autowired
    private PlatformTransactionManager platformTransactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;
    @Autowired
    private IBussinessPayOrderService payOrderService;
    @Autowired
    private IBonusGroupBillService bonusGroupBillService;

    @EventListener
    @Async
    public void notify(PayOrderNotifyEvent payOrderNotifyEvent) {
        JSONObject decryptData = payOrderNotifyEvent.getDecryptData();
        String status = decryptData.getString("status");
        String requestNo = decryptData.getString("requestNo");
        Double fee = decryptData.getDouble("fee");
        Double debitAmount = decryptData.getDouble("debitAmount");
        Double receiveAmount = decryptData.getDouble("receiveAmount");
        BussinessPayOrder payOrder = payOrderService.getByRequestNo(requestNo);
        if(payOrder == null){
            return;
        }
        if (SystemConstant.PayOrderStatus.SUCCESS.getValue().equals(payOrder.getPayStatus())
                || SystemConstant.PayOrderStatus.FAIL.getValue().equals(payOrder.getPayStatus())) {//成功或失败的订单不再处理
            return;
        } else {
            payOrder.setThirdLog(decryptData.toJSONString());
            payOrder.setChannelFee(new BigDecimal(fee));
            String[] split = payOrder.getPayFlag().split("");
            if ("SUCCESS".equals(status)) {
                log.info("======================代付回调成功========================");
                payOrder.setPayStatus(SystemConstant.PayOrderStatus.SUCCESS.getValue());
                split[1] = "1";
                payOrder.setPayFlag(StringUtil.join(split, ""));
                payOrder.setDebitAmount(new BigDecimal(debitAmount));
                payOrder.setReceiveAmount(new BigDecimal(receiveAmount.toString()));
                payOrder.setChannelFee(new BigDecimal(fee));
                payOrderService.updateById(payOrder);
//                TransactionStatus transaction = platformTransactionManager.getTransaction(transactionDefinition);
                //处理逻辑
                try {
                    if(payOrder.getBizType() == 1){ //商户代付
                        this.handleBussinessPay(payOrder, status, decryptData);
                    }else if(payOrder.getBizType() == 2){ //平台分润
                        this.handleBonus(payOrder, status);
                    }
//                    //提交事务
//                    platformTransactionManager.commit(transaction);
                }catch (Exception e){
                    //回滚事务
//                    platformTransactionManager.rollback(transaction);
                    e.printStackTrace();
                    split[1] = "2";
                    payOrder.setPayFlag(StringUtil.join(split, ""));
                    payOrder.setThirdLog(e.getMessage());
                    payOrder.setFailReason(decryptData.getString("failReason"));
                    payOrder.setPayStatus(SystemConstant.PayOrderStatus.ERROR.getValue());
                    payOrderService.updateById(payOrder);
                    if(payOrder.getBizType() == 2){
                        BonusGroupBill bill = this.bonusGroupBillService.getById(Long.valueOf(payOrder.getBizId()));
                        bill.setBonusStatus(SystemConstant.PayOrderStatus.ERROR.getValue());
                        this.bonusGroupBillService.updateById(bill);
                    }
                }
            } else {
                //第三方支付回调结果为失败，记录分佣流水失败的原因
                split[1] = "2";
                payOrder.setPayFlag(StringUtil.join(split, ""));
                payOrder.setPayStatus(SystemConstant.PayOrderStatus.FAIL.getValue());
                payOrder.setFailReason(decryptData.getString("failReason"));
                payOrderService.updateById(payOrder);
            }
        }
    }

    private void handleBonus(BussinessPayOrder payOrder, String status){
        String bizId = payOrder.getBizId();
        BonusGroupBill bill = bonusGroupBillService.getById(Long.valueOf(bizId));
        bill.setBonusStatus(status);
        this.bonusGroupBillService.updateById(bill);
    }

    private void handleBussinessPay(BussinessPayOrder payOrder, String status, JSONObject decryptData){
        Long bussinessId = payOrder.getBussinessId();
        //更新当天已代付金额
        if(bussinessId != null){
            Bussiness bussiness = bussinessService.getById(bussinessId);
            BusinessDeptDaliyStat todayStat = businessDeptDailyStatService.getTodayStat(bussinessId);
            todayStat.setStatAmount(todayStat.getStatAmount().add(payOrder.getOrderAmount()));
            this.businessDeptDailyStatService.updateById(todayStat);
            //更新商户余额信息
            R<BigDecimal> newRemainR = this.bussinessService.queryBalance(bussiness.getMerchantNo());
            BigDecimal newRemain = newRemainR.getData();
            bussiness.setRemain(MoneyDesUtil.encrypt(newRemain.toString(), MoneyDesUtil.KEY_FOR_UC));
            //修改商户余额信息
            bussinessService.updateById(bussiness);
        }
        //通知回调给采购商
        NotifyDto dto = new NotifyDto();
        dto.setBussinessOrderId(payOrder.getBussinessOrderId());//商户提供的订单号
        dto.setStatus(status);
        dto.setBankCode(decryptData.getString("bankCode"));
        dto.setUserName(decryptData.getString("receiverAccountName"));
        dto.setReceiveAmount(decryptData.getString("receiveAmount"));
        dto.setBankCardNo(decryptData.getString("receiverAccountNo"));
        dto.setFailReason(decryptData.getString("failReason"));
        this.recallToBusiness(payOrder.getBizPayNotifyUrl(), dto);
    }

    private void recallToBusiness(String url, NotifyDto notifyDto){
        log.info("===============采购商用户代付单订阅回调==================");
        log.info(notifyDto.toString());
        if(StringUtil.isNotBlank(url)){
            try{
                RestTemplate restTemplate = new RestTemplate();
                HttpHeaders headers = new HttpHeaders();
                headers.add(HttpHeaders.CONTENT_TYPE, "application/json");
                HttpEntity<String> requestEntity = new HttpEntity<String>(JSONUtil.toJsonStr(notifyDto), headers);
                ParameterizedTypeReference<Object> reference = new ParameterizedTypeReference<Object>() {
                };
                URI uri = URI.create(url);
                restTemplate.exchange(uri, HttpMethod.POST, requestEntity, reference);
            }catch (Exception e){
                e.printStackTrace();
                log.error("采购商用户代付单回调地址>>>>>>>>>>>>>> " + url);
                log.error("采购商用户代付单回调地址请求失败");
                log.error(JSONUtil.toJsonStr(notifyDto));
            }
        }
    }

    /**
     * 订单失败，释放掉商户的相应冻结金额
     * @param debit
     * @param bussiness
     */
    private void subtractFreeze(BussinessDebit debit, Bussiness bussiness){
        //减掉相应的商户冻结金额
        BigDecimal bussinessFreeze = new BigDecimal(MoneyDesUtil.decrypt(bussiness.getFreeze(), MoneyDesUtil.KEY_FOR_UC));
        BigDecimal subtract = bussinessFreeze.subtract(debit.getPrice());
        bussiness.setFreeze(MoneyDesUtil.encrypt(subtract.toString(), MoneyDesUtil.KEY_FOR_UC));
    }

    public static void main(String[] args){
        String a = "10";
        String[] split = a.split("");
        split[1] = "1";
        String b = StringUtil.join(split, "");
        System.out.println(b);
    }
}
