package cn.pluss.platform.ys.impl;

import cn.pluss.platform.api.SplitReq;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.merchantChannelStatus.MerchantChannelStatusService;
import cn.pluss.platform.merchantOrder.BaseMercSplitService;
import cn.pluss.platform.util.DateUtils;
import cn.pluss.platform.util.StringUtil;
import cn.pluss.platform.yinsheng.ReqOldEntity;
import cn.pluss.platform.yinsheng.YsOldSrcMerchantNo;
import cn.pluss.platform.ys.*;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

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

/**
 * TODO
 * 银盛分账服务类
 * @author crystal
 * @date 2022/7/1 11:49
 */
@Service("ysMercSplitService")
@Slf4j
public class YsMercSplitServiceImpl implements BaseMercSplitService {

    @Resource
    private YsService ysService;

    @Resource
    private YsConfig ysConfig;

    @Resource
    private MerchantChannelStatusService merchantChannelStatusService;

    /**
     * 分账登记
     * @param order
     * @param detailList
     * @return
     */
    @Override
    public boolean split(MerchantOrderSplit order, List<MerchantOrderSplitDetail> detailList,MerchantChannelStatus channel) {
        JSONObject reqData = new JSONObject();
        JSONArray divList = new JSONArray(detailList.size());
        reqData.put("out_trade_no",order.getOrderNumber());
        reqData.put("payee_usercode",channel.getMerchantId());
        reqData.put("total_amount",order.getOrderAmt());
        //原订单是否参与分账 01是02否
        reqData.put("is_divistion",MerchantOrderSplit.DEFAULT_IS_DIVISTION);
        //是否重新分账
        reqData.put("is_again_division",MerchantOrderSplit.DEFAULT_IS_AGAIN_DIVISION);
        reqData.put("division_mode",order.getDivisionMode());
        for (MerchantOrderSplitDetail detail:detailList) {
            JSONObject result = new JSONObject();
            result.put("division_mer_usercode",detail.getMerchantId());
            if(SplitReq.DivisionMode.SCALE.getValue().equals(order.getDivisionMode())){
                result.put("div_ratio",detail.getDivRatio());
                detail.setFinalAmt(order.getOrderAmt().multiply(detail.getDivRatio()).setScale(2,BigDecimal.ROUND_HALF_UP));
            }
            if(SplitReq.DivisionMode.AMT.getValue().equals(order.getDivisionMode())){
                result.put("div_amount",detail.getDivAmt());
                detail.setFinalAmt(detail.getDivAmt());
            }
            result.put("is_chargeFee",detail.getIsChargeFee());
            detail.setIsChargeFee(detail.getIsChargeFee());
            divList.add(result);
        }
        reqData.put("div_list",divList);
        JSONObject result = ysService.requestOldApiCommon(ysConfig.getOtherDomain(), reqData, YsService.TYPE_PAY, YsEnum.YS_SPLIT_ACCEPT,channel.getSrcMerchantNo());
        String msg = result.getString("msg");
        String sub_msg = result.getString("sub_msg");
        String code = result.getString("code");
        order.setRemark(StringUtil.isNotEmpty(sub_msg) ? sub_msg :msg);
        if(YSConstants.SUCCESS_CODE.equals(code)){
            String returnInfo = result.getString("retrunInfo");
            String returnCode = result.getString("returnCode");
            order.setDivStatusCode(returnCode);
            order.setRemark(returnInfo);
            if("0000".equals(returnCode)){
                order.setDivStatus(1);
                return true;
            }
            order.setDivStatus(-1);
            return false;
        }
        log.error("【银盛分账登记】接口请求失败：订单号：{}，失败原因：{}",order.getOrderNumber(),result.getString("msg"));
        return false;
    }

    /**
     * 分账登记
     * @param order
     * @param settingList
     * @param flag
     * @return
     */
    @Override
    public MerchantOrderSplit split(MerchantOrder order, List<MerchantSplitSetting> settingList,boolean flag) {
        MerchantChannelStatus channel = merchantChannelStatusService.getByMerchantId(settingList.get(0).getChieMerchantId());
        JSONObject reqData = new JSONObject();
        reqData.put("out_trade_no",order.getOrderNumber());
        reqData.put("payee_usercode",settingList.get(0).getChieMerchantId());
        reqData.put("total_amount",order.getConsumeFee());
        //原订单是否参与分账 01是02否
        reqData.put("is_divistion",MerchantOrderSplit.DEFAULT_IS_DIVISTION);
        //是否重新分账
        reqData.put("is_again_division",MerchantOrderSplit.DEFAULT_IS_AGAIN_DIVISION);
        JSONArray divList = new JSONArray(settingList.size());
        reqData.put("division_mode",settingList.get(0).getDivisionMode());
        MerchantOrderSplit splitOrder = new MerchantOrderSplit(order,channel,settingList.get(0).getDivisionMode(),settingList.get(0).getNotifyUrl());
        List<MerchantOrderSplitDetail> detailList = new ArrayList<>(settingList.size());
        BigDecimal scale = BigDecimal.ZERO;
        for (MerchantSplitSetting setting:settingList) {
            MerchantOrderSplitDetail detail = new MerchantOrderSplitDetail();
            detail.setIsChargeFee(setting.getIsChargeFee());
            JSONObject result = new JSONObject();
            detail.setOrderNumber(order.getOrderNumber());
            detail.setMerchantCode(setting.getDiviMerchantCode());
            detail.setMerchantId(setting.getDiviMerchantId());
            result.put("division_mer_usercode",setting.getDiviMerchantId());
            if(SplitReq.DivisionMode.SCALE.getValue().equals(settingList.get(0).getDivisionMode())){
                result.put("div_ratio",setting.getDivRatio());
                detail.setDivRatio(setting.getDivRatio());
                scale = scale.add(setting.getDivRatio());
                detail.setFinalAmt(BigDecimal.valueOf(order.getConsumeFee()).multiply(setting.getDivRatio()).setScale(2,BigDecimal.ROUND_HALF_UP));
            }
            if(SplitReq.DivisionMode.AMT.getValue().equals(settingList.get(0).getDivisionMode())){
                result.put("div_amount",setting.getDivAmt());
                detail.setDivAmt(setting.getDivAmt());
            }
            result.put("is_chargeFee",!flag ? MerchantSplitSetting.YES_IS_CHARGEFEE : setting.getIsChargeFee());
            detail.setIsChargeFee(!flag ? MerchantSplitSetting.YES_IS_CHARGEFEE : setting.getIsChargeFee());
            divList.add(result);
            detailList.add(detail);
        }
        if(SplitReq.DivisionMode.SCALE.getValue().equals(settingList.get(0).getDivisionMode()) && flag){
            MerchantOrderSplitDetail chiDetail = new MerchantOrderSplitDetail();
            chiDetail.setOrderNumber(order.getOrderNumber());
            chiDetail.setMerchantCode(settingList.get(0).getChieMerchantCode());
            chiDetail.setMerchantId(settingList.get(0).getChieMerchantId());
            BigDecimal cxScale = BigDecimal.ONE.subtract(scale);
            chiDetail.setDivRatio(cxScale);
            JSONObject chiResult = new JSONObject();
            chiResult.put("division_mer_usercode",settingList.get(0).getChieMerchantId());
            chiResult.put("div_ratio",cxScale);
            chiResult.put("is_chargeFee",MerchantSplitSetting.YES_IS_CHARGEFEE);
            detailList.add(chiDetail);
            divList.add(chiResult);
            chiDetail.setIsChargeFee(MerchantSplitSetting.YES_IS_CHARGEFEE);
            chiDetail.setFinalAmt(BigDecimal.valueOf(order.getConsumeFee()).multiply(cxScale).setScale(2,BigDecimal.ROUND_HALF_UP));
        }
        reqData.put("div_list",divList);
        JSONObject result = ysService.requestOldApiCommon(ysConfig.getOtherDomain(), reqData, YsService.TYPE_PAY, YsEnum.YS_SPLIT_ACCEPT,channel.getSrcMerchantNo());
        splitOrder.setPayTime(order.getTransDt());
        splitOrder.setStatus(1);
        splitOrder.setMercOrderNo(order.getMercOrderNo());
        splitOrder.setDetailList(detailList);
        if(YSConstants.SUCCESS_CODE.equals(result.getString("code"))){
            String returnInfo = result.getString("retrunInfo");
            String returnCode = result.getString("returnCode");
            if("0000".equals(returnCode)){
                splitOrder.setDivStatus(1);
            }else{
                splitOrder.setDivStatus(-1);
            }
            splitOrder.setDivStatusCode(returnCode);
            splitOrder.setRemark(returnInfo);
            return splitOrder;
        }
        splitOrder.setDivStatus(-1);
        splitOrder.setDivStatusCode(result.getString("code"));
        log.error("【银盛分账登记】接口请求失败：订单号：{}，失败原因：{}",order.getOrderNumber(),result.getString("msg"));
        splitOrder.setRemark(result.getString("msg"));
        return splitOrder;
    }

    /**
     * 分账退款接口
     * @param refund
     * @return
     */
    @Override
    public boolean refund(MerchantOrderSplitRefund refund) {
        JSONObject req = new JSONObject(16);
        req.put("out_trade_no",refund.getOrderNumber());
        req.put("shopdate", DateUtils.toString(refund.getOrderTime(),"yyyyMMdd"));
        req.put("refund_amount",refund.getRefundAmt());
        req.put("refund_reason",refund.getRefundReason());
        req.put("out_request_no",refund.getRefundNo());
        req.put("is_division",MerchantOrderSplit.DEFAULT_IS_DIVISTION);
        req.put("ori_division_mode",refund.getDivisionMode());
        req.put("refund_split_info",refund.getRefundDivList());
        req.put("order_div_list",refund.getOrderDivList());
        JSONObject result = ysService.requestOldApiCommon(ysConfig.getCommonDomain(), req, YsService.TYPE_PAY, YsEnum.YS_SPLIT_REFUND, YsOldSrcMerchantNo.SYB.getValue());
        String msg = result.getString("msg");
        String sub_msg = result.getString("sub_msg");
        refund.setRemark(StringUtil.isNotEmpty(sub_msg) ? sub_msg :msg);
        if(YSConstants.SUCCESS_CODE.equals(result.getString("code"))){
            refund.setStatus(1);
            refund.setRefundTime(new Date());
            return true;
        }
        return false;
    }

    /**
     * 一般消费户退款接口
     * @param refund
     * @return
     */
    @Override
    public boolean generalRefund(MerchantOrderSplitRefund refund) {
        JSONObject req = new JSONObject(16);
        req.put("out_trade_no",refund.getOrderNumber());
        req.put("shopdate", DateUtils.toString(refund.getOrderTime(),"yyyyMMdd"));
        req.put("refund_amount",refund.getRefundAmt());
        req.put("refund_reason",refund.getRefundReason());
        req.put("out_request_no",refund.getRefundNo());
        req.put("is_division",MerchantOrderSplit.DEFAULT_IS_DIVISTION);
        req.put("refund_split_info",refund.getRefundDivList());
        JSONObject result = ysService.requestOldApiCommon(ysConfig.getCommonDomain(), req, YsService.TYPE_PAY, YsEnum.YS_SPLIT_GENERAL_REFUND,YsOldSrcMerchantNo.SYB.getValue());
        String msg = result.getString("msg");
        String sub_msg = result.getString("sub_msg");
        String code = result.getString("code");
        refund.setRemark(StringUtil.isNotEmpty(sub_msg) ? sub_msg : msg);
        if(YSConstants.SUCCESS_CODE.equals(code)){
            refund.setChannelRefundNo(result.getString("refundsn"));
            refund.setStatus(1);
            refund.setRefundTime(new Date());
            return true;
        }
        return false;
    }

    /**
     * 分账订单查询接口
     * @param order
     */
    @Override
    public List<MerchantOrderSplitDetail> splitQuery(MerchantOrderSplit order,List<MerchantOrderSplitDetail> detailList) {
        JSONObject reqData = new JSONObject(10);
        reqData.put("src_usercode",order.getMerchantId());
        reqData.put("out_trade_no",order.getOrderNumber());
        YsEnum ysEnum = YsEnum.YS_SPLIT_QUERY;
        JSONObject response = ysService.requestOldApiCommon(ysConfig.getOtherDomain(), reqData, YsService.TYPE_OTHER, ysEnum,YsOldSrcMerchantNo.SYB.getValue());
        String code = response.getString("code");
        String msg = response.getString("msg");
        if(!YSConstants.SUCCESS_CODE.equals(code)){
            MsgException.throwException(msg);
        }
        JSONArray detailResults = response.getJSONArray("detailResults");
        if(detailResults == null){
            String note = response.getString("note");
            log.info("【银盛分账查询】订单号:{},note:{},返回参数：{}",order.getOrderNumber(),note,response.toJSONString());
            return null;
        }
        BigDecimal fee = response.getBigDecimal("fee");
        String fee_payer = response.getString("fee_payer");
        String divisionStatus = response.getString("division_status");
        String divisionStatusCode = response.getString("division_status_code");
        String note = response.getString("note");
        order.setFee(fee);
        order.setFeePayer(fee_payer);
        order.setDivStatusCode(divisionStatusCode);
        order.setRemark(note);
        Integer divStatus = null;
        switch (divisionStatus){
            case "01":
                divStatus = 1;
                break;
            case "02":
                divStatus = 3;
                break;
            case "00":
                divStatus = 2;
                break;
            case "03":
                divStatus = 4;
                break;
            default:
                divStatus = -1;
                break;
        }
        order.setDivStatus(divStatus);
        for (int i = 0 ; i < detailResults.size(); i++) {
            JSONObject o = detailResults.getJSONObject(i);
            MerchantOrderSplitDetail detail = detailList.get(i);
            detail.setFinalAmt(o.getBigDecimal("division_amount"));
        }
        return detailList;
    }

    /**
     * 分账退款查询
     * @param qRefund
     * @param srList
     * @return
     */
    @Override
    public List<MerchantOrderSplitDetail> refundQuery(MerchantOrderSplitRefund qRefund, List<MerchantOrderSplitDetail> srList) {
        JSONObject reqData = new JSONObject(16);
        reqData.put("out_request_no",qRefund.getRefundNo());
        reqData.put("out_trade_no",qRefund.getOrderNumber());
        YsEnum ysEnum = YsEnum.REFUND_PAY_QUERY;
        JSONObject response = ysService.requestOldApiCommon(ysConfig.getCommonDomain(), reqData, YsService.TYPE_OTHER, ysEnum,YsOldSrcMerchantNo.SYB.getValue());
        String code = response.getString("code");
        String msg = response.getString("msg");
        if(!YSConstants.SUCCESS_CODE.equals(code)){
            MsgException.throwException(msg);
        }
        String refund_state = response.getString("refund_state");
        switch (refund_state){
            case "success":
                qRefund.setStatus(1);
            case "fail":
                qRefund.setStatus(2);
            default:
                qRefund.setStatus(0);
        }
        String funds_state = response.getString("funds_state");
        String desc = "";
        switch (funds_state){
            case "success":
                desc = "退款成功";
                break;
            case "in_process":
                desc = "退款处理中";
                break;
            case "fail_to_manual_deal":
                desc = "退款失败，待人工处理，有疑问请联系商务经理";
                break;
            case "fail_due_manual_close":
                desc = "退款失败，人工关闭，有疑问请联系商务经理";
                break;
            case "fail":
                desc = "退款失败";
                break;
        }
        qRefund.setChannelFundsDesc(desc);
        qRefund.setChannelRefundState(refund_state);
        qRefund.setChannelFundsState(funds_state);
        String refund_channelfunds_dynamics = response.getString("refund_channelfunds_dynamics");
        JSONArray parse = JSONArray.parseArray(refund_channelfunds_dynamics);
        for (int i = 0 ; i < parse.size(); i++) {
            JSONObject jsonObject = parse.getJSONObject(i);
            BigDecimal refundamount = jsonObject.getBigDecimal("refundamount");
            String state = jsonObject.getString("state");
            String channelSendSn = jsonObject.getString("channelSendSn");
            String channelRecvSn = jsonObject.getString("channelRecvSn");
            MerchantOrderSplitDetail detail = srList.get(i);
            detail.setRefundAmt(refundamount);
            detail.setStatus(-1);
            detail.setState(state);
            detail.setChannelSendSn(channelSendSn);
            detail.setChannelRecvSn(channelRecvSn);
        }
        return srList;
    }

    /**
     * 商户提现
     * @param order
     */
    @Override
    public void withdraw(MerchantOrderSplit order, MerchantChannelStatus channel) {
        JSONObject reqData = new JSONObject(16);
        reqData.put("out_trade_no",order.getOrderNumber());
        reqData.put("merchant_usercode",channel.getMerchantId());
        reqData.put("currency","CNY");
        reqData.put("total_amount",order.getOrderAmt());
        reqData.put("subject","发起提现");
        reqData.put("shopdate",DateUtils.toString(order.getCreateTime(),"yyyyMMdd"));
        reqData.put(ReqOldEntity.VERSION_NAME,ReqOldEntity.VERSION_3_1);
        YsEnum ysEnum = YsEnum.YS_MERCHANT_WITHDRAW_ACCEPT;
        JSONObject response = ysService.requestOldApiCommon(ysConfig.getOtherDomain(), reqData, YsService.TYPE_PAY, ysEnum, channel.getSrcMerchantNo());
        String code = response.getString("code");
        String msg = response.getString("msg");
    }
}
