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

import com.alibaba.fastjson.JSONObject;
import com.hfkj.channel.lakala.LaKaLaTradeService;
import com.hfkj.channel.tianque.service.TianQueTradeService;
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.entity.BsMerPlatformNo;
import com.hfkj.entity.BsTradeOrder;
import com.hfkj.entity.BsTradeOrderRefund;
import com.hfkj.dao.OpenApiTradeOrderMapper;
import com.hfkj.openapi.v1.model.TradeDetailBillsModel;
import com.hfkj.openapi.v1.model.TradeRefundBillsModel;
import com.hfkj.openapi.v1.model.request.RequestRefundTradeModel;
import com.hfkj.openapi.v1.model.response.ResponseRefundTradeModel;
import com.hfkj.openapi.v1.model.TradeBillsModel;
import com.hfkj.openapi.v1.service.OpenApiTradeOrderService;
import com.hfkj.openapi.v1.utils.SignatureUtil;
import com.hfkj.service.BsMerKeyService;
import com.hfkj.service.BsMerPlatformNoService;
import com.hfkj.service.BsTradeOrderRefundService;
import com.hfkj.service.BsTradeOrderService;
import com.hfkj.sysenum.PlatformTypeEnum;
import com.hfkj.sysenum.TradeOrderRefundStatusEnum;
import com.hfkj.sysenum.TradeOrderRefundTypeEnum;
import com.hfkj.sysenum.TradeOrderStatusEnum;
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.Date;
import java.util.List;
import java.util.Map;

/**
 * @className: TradeOrderServiceImpl
 * @author: HuRui
 * @date: 2023/5/24
 **/
@Service("openApiTradeOrderService")
public class OpenApiTradeOrderServiceImpl implements OpenApiTradeOrderService {

    @Resource
    private OpenApiTradeOrderMapper openApiTradeOrderMapper;
    @Resource
    private BsTradeOrderService bsTradeOrderService;
    @Resource
    private BsTradeOrderRefundService bsTradeOrderRefundService;
    @Resource
    private BsMerKeyService merKeyService;
    @Resource
    private LaKaLaTradeService laKaLaTradeService;
    @Resource
    private TianQueTradeService tianQueTradeService;
    @Resource
    private BsMerPlatformNoService merPlatformNoService;

    @Override
    @Transactional(propagation= Propagation.REQUIRES_NEW)
    public Map<String, Object> createOrder(BsTradeOrder tradeOrder) throws Exception {
        bsTradeOrderService.editOrder(tradeOrder);

        BsMerPlatformNo platform = merPlatformNoService.getCurrentPlatform(tradeOrder.getMerId());
        if (platform == null) {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "未配置支付渠道");
        }
        Map<String, Object> preorder;
        if (platform.getPlatformType().equals(PlatformTypeEnum.type1.getNumber())) {
            preorder = laKaLaTradeService.preorder(tradeOrder.getOutTradeNo());

        } else if (platform.getPlatformType().equals(PlatformTypeEnum.type5.getNumber())) {
            preorder = tianQueTradeService.preorder(tradeOrder.getOutTradeNo());

        } else {
            throw ErrorHelp.genException(SysCode.OpenApi, ErrorCode.OPEN_API_COMMON, "未知的支付渠道");
        }

        preorder.put("merchantNo", tradeOrder.getMerNo());
        preorder.put("outTradeNo", tradeOrder.getOutTradeNo());

        // 取出支付参数
        JSONObject payParam = JSONObject.parseObject(MapUtils.getString(preorder, "payParam"));
        preorder.put("payParam", payParam.getJSONObject("acc_resp_fields"));
        preorder.remove("platformType");
        preorder.remove("order");
        preorder.put("sign", SignatureUtil.createSign(preorder, merKeyService.getKeyByMerNo(tradeOrder.getMerNo())));
        return preorder;
    }

    @Override
    public BsTradeOrder getOrderByOutTradeNo(String outTradeNo) {
        return bsTradeOrderService.getOrderByOutTradeNo(outTradeNo);
    }

    @Override
    public ResponseRefundTradeModel refund(RequestRefundTradeModel refundTrade) throws Exception {
        // 查询交易订单
        BsTradeOrder tradeOrder = getOrderByOutTradeNo(refundTrade.getOutTradeNo());
        if (tradeOrder == null) {
            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, "交易订单状态不处于已支付");
        }

        BsTradeOrderRefund orderRefund = new BsTradeOrderRefund();
        orderRefund.setSalesmanId(tradeOrder.getSalesmanId());
        orderRefund.setAgentId(tradeOrder.getAgentId());
        orderRefund.setMerId(tradeOrder.getMerId());
        orderRefund.setStoreId(tradeOrder.getStoreId());

        orderRefund.setPlatformType(tradeOrder.getPlatformType());
        orderRefund.setTradeOrderId(tradeOrder.getId());
        orderRefund.setOutTradeNo(tradeOrder.getOutTradeNo());
        orderRefund.setRefundNo(refundTrade.getRefundTradeNo());
        orderRefund.setTotalAmount(tradeOrder.getTradeAmount());
        orderRefund.setRefundAmount(new BigDecimal(refundTrade.getRefundAmount()));
        orderRefund.setRefundReason(refundTrade.getRefundReason());
        orderRefund.setStatus(TradeOrderRefundStatusEnum.status1.getNumber());
        orderRefund.setOperatorId(0L);
        orderRefund.setOperatorName("API接口");
        bsTradeOrderRefundService.editOrderRefund(orderRefund);

        Map<String, Object> refundMap = bsTradeOrderRefundService.tradeOrderRefund(orderRefund);
        orderRefund = (BsTradeOrderRefund) refundMap.get("orderRefund");

        ResponseRefundTradeModel refundTradeModel = new ResponseRefundTradeModel();
        refundTradeModel.setMerchantNo(tradeOrder.getMerNo());
        refundTradeModel.setOutTradeNo(tradeOrder.getOutTradeNo());
        refundTradeModel.setPayMode(tradeOrder.getPayMode());
        refundTradeModel.setRefundTradeNo(orderRefund.getRefundNo());
        refundTradeModel.setAccTradeNo(orderRefund.getAccTradeNo());
        refundTradeModel.setRefundAmount(orderRefund.getRefundAmount().toString());
        refundTradeModel.setRefundPayerAmount(orderRefund.getPayerAmount().toString());
        refundTradeModel.setRefundTime(orderRefund.getRefundTime());
        refundTradeModel.setSign(SignatureUtil.createSign(refundTradeModel, merKeyService.getKeyByMerNo(tradeOrder.getMerNo())));

        tradeOrder.setRefundPrice(tradeOrder.getRefundPrice().add(orderRefund.getRefundAmount()));
        if (tradeOrder.getRefundPrice().compareTo(tradeOrder.getTradeActualAmount()) == 0) {
            tradeOrder.setRefundType(TradeOrderRefundTypeEnum.type1.getNumber());
            tradeOrder.setStatus(TradeOrderStatusEnum.status6.getNumber());
        } else {
            tradeOrder.setRefundType(TradeOrderRefundTypeEnum.type2.getNumber());
        }
        bsTradeOrderService.editOrder(tradeOrder);
        return refundTradeModel;
    }

    @Override
    public BsTradeOrderRefund getRefundByNo(String refundNo) {
        return bsTradeOrderRefundService.getRefundByRefundNo(refundNo);
    }

    @Override
    public List<TradeBillsModel> tradeBills(String merNo, Long billDateS, Long billDateE) {
        return openApiTradeOrderMapper.queryTradeBills(merNo,
                DateUtil.date2String(new Date(billDateS), DateUtil.Y_M_D_HMS),
                DateUtil.date2String(new Date(billDateE), DateUtil.Y_M_D_HMS)
        );
    }

    @Override
    public List<TradeRefundBillsModel> tradeRefundBills(String merNo, Long billDateS, Long billDateE) {
        return openApiTradeOrderMapper.queryRefundBills(merNo,
                DateUtil.date2String(new Date(billDateS), DateUtil.Y_M_D_HMS),
                DateUtil.date2String(new Date(billDateE), DateUtil.Y_M_D_HMS)
        );
    }

    @Override
    public List<TradeDetailBillsModel> tradeSettleBills(String merNo, Long billDateS, Long billDateE) {
        return openApiTradeOrderMapper.queryTradeSettleBills(merNo,
                DateUtil.date2String(new Date(billDateS), DateUtil.Y_M_D),
                DateUtil.date2String(new Date(billDateE), DateUtil.Y_M_D)
        );
    }

}
