package com.hfkj.openapi.v1.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.hfkj.channel.lakala.LaKaLaTradeSeparateService;
import com.hfkj.channel.lakala.LaKaLaTradeService;
import com.hfkj.common.exception.ErrorCode;
import com.hfkj.common.exception.ErrorHelp;
import com.hfkj.common.exception.SysCode;
import com.hfkj.common.utils.DateUtil;
import com.hfkj.dao.OpenApiTradeOrderMapper;
import com.hfkj.entity.*;
import com.hfkj.openapi.v1.model.TradeBillsModel;
import com.hfkj.openapi.v1.model.request.*;
import com.hfkj.openapi.v1.model.response.*;
import com.hfkj.openapi.v1.service.OpenApiTradeOrderProfitSharingService;
import com.hfkj.openapi.v1.service.OpenApiTradeOrderService;
import com.hfkj.openapi.v1.utils.SignatureUtil;
import com.hfkj.service.*;
import com.hfkj.sysenum.*;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @className: TradeOrderServiceImpl
 * @author: HuRui
 * @date: 2023/5/24
 **/
@Service("openApiTradeOrderProfitSharingService")
public class OpenApiTradeOrderProfitSharingServiceImpl implements OpenApiTradeOrderProfitSharingService {

    @Resource
    private BsTradeOrderProfitSharingService tradeOrderProfitSharingService;
    @Resource
    private BsTradeOrderProfitSharingReceiverService tradeOrderProfitSharingReceiverService;
    @Resource
    private BsMerService merService;
    @Resource
    private BsMerKeyService merKeyService;
    @Resource
    private BsMerLedgerService merLedgerService;
    @Resource
    private OpenApiTradeOrderService openApiTradeOrderService;
    @Resource
    private LaKaLaTradeSeparateService laKaLaTradeSeparateService;

    @Override
    @Transactional(propagation= Propagation.REQUIRES_NEW, timeout = 20)
    public ResponseSeparateModel separate(RequestSeparateModel separateModel) throws Exception {
        // 查询交易订单
        BsTradeOrder tradeOrder = openApiTradeOrderService.getOrderByOutTradeNo(separateModel.getOutTradeNo());
        if (tradeOrder == null) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "未知的交易单号");
        }
        if (!tradeOrder.getMerNo().equals(separateModel.getMerchantNo())) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "未知的交易单号");
        }
        if (!tradeOrder.getStatus().equals(TradeOrderStatusEnum.status3.getNumber())) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "交易订单不处于已支付");
        }
        if (tradeOrder.getProfitSharingStatus().equals(false)) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "交易订单不支持分账");
        }
        BsTradeOrderProfitSharing tradeOrderProfitSharing = new BsTradeOrderProfitSharing();
        tradeOrderProfitSharing.setCmdType(ProfitSharingCmdTypeEnum.CMD_TYPE_1.getNumber());
        tradeOrderProfitSharing.setTradeOrderId(tradeOrder.getId());
        tradeOrderProfitSharing.setTradeOrderNo(tradeOrder.getOutTradeNo());
        tradeOrderProfitSharing.setProfitSharingOrderNo(separateModel.getOutSeparateNo());
        tradeOrderProfitSharing.setPlatformType(tradeOrder.getPlatformType());
        tradeOrderProfitSharing.setPlatformMerNo(tradeOrder.getPlatformMerNo());
        tradeOrderProfitSharing.setPlatformTradeNo(tradeOrder.getPlatformTradeNo());
        tradeOrderProfitSharing.setPlatformAppid(tradeOrder.getPlatformAppid());
        tradeOrderProfitSharing.setProfitSharingAmoun(new BigDecimal(separateModel.getTotalAmount()));
        tradeOrderProfitSharing.setProfitSharingTime(new Date());
        tradeOrderProfitSharing.setStatus(ProfitSharingStatusEnum.status0.getNumber());
        tradeOrderProfitSharing.setCreateType(TradeOrderProfitSharingCreateType.type2.getNumber());
        tradeOrderProfitSharingService.editData(tradeOrderProfitSharing);

        for (RequestSeparateModel.RequestSeparateRecvDataModel recvData : separateModel.getRecvDatas()) {
            BsMer recvMer = merService.getMer(recvData.getRecvMerchantNo());
            BsMerLedger merLedger = merLedgerService.getMerLedger(recvMer.getId(), PlatformTypeEnum.type1);
            BsTradeOrderProfitSharingReceiver profitSharingReceiver = new BsTradeOrderProfitSharingReceiver();
            profitSharingReceiver.setTradeOrderProfitSharingId(tradeOrderProfitSharing.getId());
            profitSharingReceiver.setTradeOrderId(tradeOrder.getId());
            profitSharingReceiver.setTradeOrderNo(tradeOrder.getOutTradeNo());
            profitSharingReceiver.setProfitSharingAmount(tradeOrderProfitSharing.getProfitSharingAmoun());
            profitSharingReceiver.setReceiverObjectType(ProfitSharingReceiverObjectType.mer.getType());
            profitSharingReceiver.setReceiverObjectId(recvMer.getId().toString());
            profitSharingReceiver.setReceiverNo(recvMer.getMerNo());
            profitSharingReceiver.setReceiverAccount(merLedger.getReceiverNo());
            profitSharingReceiver.setReceiverName(recvMer.getMerName());
            profitSharingReceiver.setReceiverAmount(new BigDecimal(recvData.getSeparateAmount()));
            tradeOrderProfitSharingReceiverService.editData(profitSharingReceiver);
        }

        // 调用第三方分账
        BsTradeOrderProfitSharing profitSharing = laKaLaTradeSeparateService.separate(tradeOrderProfitSharing.getProfitSharingOrderNo());

        ResponseSeparateModel responseSeparate = new ResponseSeparateModel();
        responseSeparate.setMerchantNo(separateModel.getMerchantNo());
        responseSeparate.setOutSeparateNo(separateModel.getOutSeparateNo());
        responseSeparate.setSeparateNo(profitSharing.getPlatformProfitSharingOrderNo());
        responseSeparate.setStatus(profitSharing.getStatus());
        responseSeparate.setTotalAmount(separateModel.getTotalAmount());
        responseSeparate.setSign(SignatureUtil.createSign(responseSeparate, merKeyService.getKeyByMerNo(responseSeparate.getMerchantNo())));
        return responseSeparate;
    }

    @Override
    @Transactional(propagation= Propagation.REQUIRES_NEW, timeout = 20)
    public ResponseSeparateCancelModel cancel(RequestSeparateCancelModel separateCancelModel) throws Exception {
        // 查询分账流水号是否存在
        BsTradeOrderProfitSharing originOutSeparate = tradeOrderProfitSharingService.getDetailByProfitSharingOrderNo(separateCancelModel.getOriginOutSeparateNo());
        if (originOutSeparate == null) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "原分账指令流水号不存在");
        }
        if (!originOutSeparate.getStatus().equals(ProfitSharingStatusEnum.status1.getNumber())) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "原分账状态错误");
        }
        if (originOutSeparate.getProfitSharingAmoun().compareTo(new BigDecimal(separateCancelModel.getTotalAmount())) != 0) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "撤销金额与分账金额不一致");
        }
        // 查询撤销分账指令流水号
        if (tradeOrderProfitSharingService.getDetailByProfitSharingOrderNo(separateCancelModel.getOutSeparateNo()) != null) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "商户分账指令流水号重复");
        }
        // 交易订单
        BsTradeOrder tradeOrder = openApiTradeOrderService.getOrderByOutTradeNo(originOutSeparate.getTradeOrderNo());
        if (tradeOrder == null) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "未知的商户指令");
        }
        if (!separateCancelModel.getMerchantNo().equals(tradeOrder.getMerNo())) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "未知的商户指令");
        }
        BsTradeOrderProfitSharing profitSharingCmd = new BsTradeOrderProfitSharing();
        profitSharingCmd.setCmdType(ProfitSharingCmdTypeEnum.CMD_TYPE_2.getNumber());
        profitSharingCmd.setTradeOrderId(tradeOrder.getId());
        profitSharingCmd.setTradeOrderNo(tradeOrder.getOutTradeNo());
        profitSharingCmd.setOriginProfitSharingOrderNo(separateCancelModel.getOriginOutSeparateNo());
        profitSharingCmd.setProfitSharingOrderNo(separateCancelModel.getOutSeparateNo());
        profitSharingCmd.setPlatformType(tradeOrder.getPlatformType());
        profitSharingCmd.setPlatformMerNo(tradeOrder.getPlatformMerNo());
        profitSharingCmd.setPlatformTradeNo(tradeOrder.getPlatformTradeNo());
        profitSharingCmd.setPlatformAppid(tradeOrder.getPlatformAppid());
        profitSharingCmd.setProfitSharingAmoun(new BigDecimal(separateCancelModel.getTotalAmount()));
        profitSharingCmd.setProfitSharingTime(new Date());
        profitSharingCmd.setStatus(ProfitSharingStatusEnum.status2.getNumber());
        profitSharingCmd.setCreateType(TradeOrderProfitSharingCreateType.type2.getNumber());
        tradeOrderProfitSharingService.editData(profitSharingCmd);

        // 调用第三方
        JSONObject responseCancel = laKaLaTradeSeparateService.cancel(separateCancelModel.getOutSeparateNo());

        ResponseSeparateCancelModel responseSeparateCancel = new ResponseSeparateCancelModel();
        responseSeparateCancel.setSeparateNo(responseCancel.getString("separate_no"));
        responseSeparateCancel.setOutSeparateNo(profitSharingCmd.getProfitSharingOrderNo());
        responseSeparateCancel.setOriginSeparateNo(originOutSeparate.getPlatformProfitSharingOrderNo());
        responseSeparateCancel.setOriginOutSeparateNo(originOutSeparate.getProfitSharingOrderNo());
        responseSeparateCancel.setStatus(profitSharingCmd.getStatus());
        responseSeparateCancel.setTotalAmount(profitSharingCmd.getProfitSharingAmoun());
        responseSeparateCancel.setSign(SignatureUtil.createSign(separateCancelModel, merKeyService.getKeyByMerNo(separateCancelModel.getMerchantNo())));
        return responseSeparateCancel;
    }

    @Override
    public ResponseSeparateQueryModel query(RequestSeparateQueryModel separateQueryModel) throws Exception {
        // 查询分账
        BsTradeOrderProfitSharing tradeOrderProfitSharing = tradeOrderProfitSharingService.getDetailByProfitSharingOrderNo(separateQueryModel.getOutSeparateNo());
        if (tradeOrderProfitSharing == null) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "未知的分账流水号");
        }
        // 交易订单
        BsTradeOrder tradeOrder = openApiTradeOrderService.getOrderByOutTradeNo(tradeOrderProfitSharing.getTradeOrderNo());
        if (tradeOrder == null) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "未知的交易流水号");
        }
        if (!separateQueryModel.getMerchantNo().equals(tradeOrder.getMerNo())) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "未知的分账流水号");
        }
        // 第三方接口查询，防止未及时更新
        if (!tradeOrderProfitSharing.getStatus().equals(ProfitSharingStatusEnum.status1.getNumber())) {
            JSONObject queryProfitSharing = laKaLaTradeSeparateService.query(separateQueryModel.getOutSeparateNo());
            if (queryProfitSharing.getString("status").equals("SUCCESS")) {
                tradeOrderProfitSharing.setFinishTime(new Date());
                tradeOrderProfitSharing.setStatus(ProfitSharingStatusEnum.status1.getNumber());
                tradeOrderProfitSharingService.editData(tradeOrderProfitSharing);

                // 修改接收方状态
                List<BsTradeOrderProfitSharingReceiver> receiverList = tradeOrderProfitSharingReceiverService.getReceiverListByProfitSharingId(tradeOrderProfitSharing.getId());
                for (BsTradeOrderProfitSharingReceiver receiver : receiverList) {
                    receiver.setStatus(ProfitSharingReceiverStatusEnum.status1.getNumber());
                    tradeOrderProfitSharingReceiverService.editData(receiver);
                }
            }
        }

        ResponseSeparateQueryModel responseSeparateQueryModel = new ResponseSeparateQueryModel();
        responseSeparateQueryModel.setCmdType(tradeOrderProfitSharing.getCmdType());
        responseSeparateQueryModel.setOutSeparateNo(tradeOrderProfitSharing.getProfitSharingOrderNo());
        responseSeparateQueryModel.setSeparateNo(tradeOrderProfitSharing.getPlatformProfitSharingOrderNo());

        responseSeparateQueryModel.setCreateDate(
                tradeOrderProfitSharing.getProfitSharingTime()!=null?
                DateUtil.date2String(tradeOrderProfitSharing.getProfitSharingTime(), "yyyyMMdd")
                : null);

        responseSeparateQueryModel.setFinishDate(
                tradeOrderProfitSharing.getFinishTime()!=null?
                DateUtil.date2String(tradeOrderProfitSharing.getFinishTime(), "yyyyMMdd")
                : null);

        responseSeparateQueryModel.setTotalAmount(tradeOrderProfitSharing.getProfitSharingAmoun());
        responseSeparateQueryModel.setStatus(tradeOrderProfitSharing.getStatus());
        // 接收方
        List<ResponseSeparateQueryModel.ResponseSeparateRecvDataModel> recvDataList = new ArrayList<>();
        if (tradeOrderProfitSharing.getCmdType().equals(ProfitSharingCmdTypeEnum.CMD_TYPE_1.getNumber())) {
            List<BsTradeOrderProfitSharingReceiver> receiverList = tradeOrderProfitSharingReceiverService.getReceiverListByProfitSharingId(tradeOrderProfitSharing.getId());
            for (BsTradeOrderProfitSharingReceiver receiver : receiverList) {
                ResponseSeparateQueryModel.ResponseSeparateRecvDataModel recvData = new ResponseSeparateQueryModel.ResponseSeparateRecvDataModel();
                recvData.setRecvMerchantNo(receiver.getReceiverNo());
                recvData.setSeparateAmount(receiver.getReceiverAmount());
                recvDataList.add(recvData);
            }
        } else if (tradeOrderProfitSharing.getCmdType().equals(ProfitSharingCmdTypeEnum.CMD_TYPE_2.getNumber())) {
            // 原分账流水
            BsTradeOrderProfitSharing originOutSeparate = tradeOrderProfitSharingService.getDetailByProfitSharingOrderNo(tradeOrderProfitSharing.getOriginProfitSharingOrderNo());
            if (originOutSeparate == null) {
                throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "未知的原分账指令流水号");
            }
            List<BsTradeOrderProfitSharingReceiver> receiverList = tradeOrderProfitSharingReceiverService.getReceiverListByProfitSharingId(originOutSeparate.getId());
            for (BsTradeOrderProfitSharingReceiver receiver : receiverList) {
                ResponseSeparateQueryModel.ResponseSeparateRecvDataModel recvData = new ResponseSeparateQueryModel.ResponseSeparateRecvDataModel();
                recvData.setRecvMerchantNo(receiver.getReceiverNo());
                recvData.setSeparateAmount(receiver.getReceiverAmount());
                recvDataList.add(recvData);
            }
        }

        responseSeparateQueryModel.setRecvDataList(recvDataList);
        responseSeparateQueryModel.setSign(SignatureUtil.createSign(responseSeparateQueryModel, merKeyService.getKeyByMerNo(separateQueryModel.getMerchantNo())));
        return responseSeparateQueryModel;
    }

    @Override
    public ResponseSeparateQueryAmtModel queryAmt(RequestSeparateQueryAmtModel separateQueryAmtModel) throws Exception {
        // 查询分账
        BsTradeOrderProfitSharing tradeOrderProfitSharing = tradeOrderProfitSharingService.getDetailByProfitSharingOrderNo(separateQueryAmtModel.getOutSeparateNo());
        if (tradeOrderProfitSharing == null) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "未知的分账流水号");
        }
        // 交易订单
        BsTradeOrder tradeOrder = openApiTradeOrderService.getOrderByOutTradeNo(tradeOrderProfitSharing.getTradeOrderNo());
        if (tradeOrder == null) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "未知的交易流水号");
        }
        if (!separateQueryAmtModel.getMerchantNo().equals(tradeOrder.getMerNo())) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "未知的分账流水号");
        }

        // 第三方查询
        JSONObject queryAmt = laKaLaTradeSeparateService.queryAmt(separateQueryAmtModel.getOutSeparateNo());
        ResponseSeparateQueryAmtModel responseSeparateQueryAmtModel = new ResponseSeparateQueryAmtModel();
        responseSeparateQueryAmtModel.setMerchantNo(separateQueryAmtModel.getMerchantNo());
        responseSeparateQueryAmtModel.setTotalSeparateAmt(queryAmt.getBigDecimal("total_separate_amt").divide(new BigDecimal("100")));
        responseSeparateQueryAmtModel.setCanSeparateAmt(queryAmt.getBigDecimal("can_separate_amt").divide(new BigDecimal("100")));
        responseSeparateQueryAmtModel.setSign(SignatureUtil.createSign(responseSeparateQueryAmtModel, merKeyService.getKeyByMerNo(separateQueryAmtModel.getMerchantNo())));
        return responseSeparateQueryAmtModel;
    }

}
