package cn.pluss.platform.jft.impl;

import cn.pluss.platform.api.Result;
import cn.pluss.platform.api.ResultGenerator;
import cn.pluss.platform.constants.Constant;
import cn.pluss.platform.dto.jft.JftPayDataDTO;
import cn.pluss.platform.dto.jft.JftReceiptOrderDTO;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.jft.JftBankCardService;
import cn.pluss.platform.jft.JftMercBaseInfoService;
import cn.pluss.platform.jft.JftMerchantRateService;
import cn.pluss.platform.jft.JftReceiptOrderService;
import cn.pluss.platform.mapper.JftReceiptInfoMapper;
import cn.pluss.platform.mapper.JftReceiptOrderMapper;
import cn.pluss.platform.mapper.RiskBlacklistMapper;
import cn.pluss.platform.merchant.JftMercPaymentChannelService;
import cn.pluss.platform.merchantOrder.MerchantOrderService;
import cn.pluss.platform.merchantProfit.MerchantProfitService;
import cn.pluss.platform.notify.NotifyMessageService;
import cn.pluss.platform.pay.PayService;
import cn.pluss.platform.sys.QueueDataService;
import cn.pluss.platform.util.ParametersUtil;
import cn.pluss.platform.util.StringUtil;
import cn.pluss.platform.vo.JftReceiptOrderVO;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.util.List;

/**
 * <p>
 * 收款单订单详情 服务实现类
 * </p>
 *
 * @author crystal
 * @since 2022-06-16
 */
@Service
@Slf4j
public class JftReceiptOrderServiceImpl extends ServiceImpl<JftReceiptOrderMapper, JftReceiptOrder> implements JftReceiptOrderService {

    @Resource
    private MerchantOrderService merchantOrderService;

    @Resource
    private QueueDataService queueDataService;

    @Resource
    private JftBankCardService jftBankCardService;

    @Resource
    private JftReceiptInfoMapper jriMapper;

    @Resource
    private JftMerchantRateService jftMerchantRateService;

    @Resource
    private JftMercBaseInfoService jftMercBaseInfoService;

    @Resource
    private JftMercPaymentChannelService jftMercPaymentChannelService;

    @Setter(onMethod_ = {@Autowired, @Qualifier("ysPayOldService")})
    private PayService ysPayOldService;

    @Resource
    private MerchantProfitService merchantProfitService;

    @Resource
    private RiskBlacklistMapper riskBlacklistMapper;

    @Setter(onMethod_ = {@Lazy, @Autowired})
    private NotifyMessageService notifyMessageService;

    public static final String API_MERC_JFT_ORDER_PREFIX = "YS_JFT_";
    /**
     * 根据收款单id盒状态查询收款单详情
     * @param id
     * @return
     */
    @Override
    public List<JftReceiptOrder> listByReceiptId(Long id,String status) {
        return baseMapper.listByReceiptId(id,status);
    }

    /**
     * 创建订单信息
     * @param entity
     * @return
     */
    @Override
    public JSONObject createOrder(JftReceiptOrderDTO entity) {
        JSONObject res = new JSONObject(16);
        entity.checkOrderParams();
        JftReceiptOrder order =  checkOrderMercInfo(entity);
        baseMapper.insert(order);
        try {
            String payUrl = ParametersUtil.domain + "/wap/aliPay/returnUrl?orderNumber="+order.getOrderNumber();
            String pUrl = URLDecoder.decode(payUrl, "UTF-8");
            res.put("payUrl",Constant.ALIPAY_H5_PAY_URL_PRIFIX + pUrl);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            MsgException.throwException("转码异常！");
        }
        res.put("mercOrderNo",order.getMercOrderNo());
        res.put("orderAmt",order.getAmount());
        res.put("orderNumber",order.getOrderNumber());
        return res;
    }

    private JftReceiptOrder checkOrderMercInfo(JftReceiptOrderDTO order) {
        JftReceiptOrder orderByNo = baseMapper.getMercOrderByNo(order.getMercOrderNo());
        MsgException.check(orderByNo != null,"订单号重复");
        String merchantCode = order.getMerchantCode();
        JftMercBaseInfo mercBaseInfo = jftMercBaseInfoService.getMercBaseInfo(order.getUserId());
        MsgException.checkNull(mercBaseInfo,"商户信息异常");
        if(StringUtil.isNotEmpty(merchantCode)){
            MsgException.check(!merchantCode.equals(mercBaseInfo.getMerchantCode()),"商户号和用户不匹配！");
        }
        JftMerchantRate mercRate = jftMerchantRateService.getRateByUserId(order.getUserId());
        MsgException.checkNull(mercRate,"商户费率异常");
        JftMercPaymentChannel channel = jftMercPaymentChannelService.getByUserId(order.getUserId());
        MsgException.checkNull(channel,"进件信息异常");
        MsgException.check(!channel.isPayment(),"商户状态不可用");
        List<RiskBlacklist> list = riskBlacklistMapper.getByUserId(order.getUserId());
        MsgException.check(!list.isEmpty(),"黑名单用户，不允许使用该功能");
        order.setMerchantName(mercBaseInfo.getMerchantName());
        order.setMerchantCode(mercBaseInfo.getMerchantCode());
        orderByNo = new JftReceiptOrder(order,mercRate,Constant.PAY_TYPE_ALIPAY,API_MERC_JFT_ORDER_PREFIX);
        orderByNo.setJftMerc(mercBaseInfo);
        orderByNo.setJftChannel(channel);
        calcOrderFee(orderByNo);
        return orderByNo;
    }

    /**
     * 根据订单号查询订单信息
     * @param ordNo
     * @return
     */
    @Override
    public JftReceiptOrder getOrderByNo(String ordNo) {
        return baseMapper.getOrderByNo(ordNo);
    }

    /**
     * 缴费通支付回调处理
     * @param receiptOrder
     */
    @Override
    public void updatePaySuccessNotify(JftReceiptOrder receiptOrder) {
        Integer row = queueDataService.newQueueData(receiptOrder.getOrderNumber());
        if(row > 0){
            //订单已支付 无需处理
            if(JftReceiptOrder.PAY_STATUS_YES.equals(receiptOrder.getStatus())){
                return;
            }
            receiptOrder.setStatus(JftReceiptOrder.PAY_STATUS_YES);
            //计算订单手续费
            calcOrderFee(receiptOrder);
            //修改订单状态
            receiptOrder.setCreateDate(null);
            updateById(receiptOrder);
            //插入订单表数据
            MerchantOrder order = new MerchantOrder();
            order.convert(receiptOrder);
            merchantProfitService.createOrderProfitV2(order,"2");
            merchantOrderService.save(order);
            //推送下游订单通知
            notifyMessageService.sendLowerPayNotifyCallback(order);
        }
    }

    @Override
    public Result<Object> tradePay(JftPayDataDTO dto, HttpServletRequest request) {
        dto.checkParams();
        JftReceiptInfo info = checkMercInfo(dto);
        JftReceiptOrder order = new JftReceiptOrder(dto,info,Constant.PAY_TYPE_ALIPAY,info.getJftMerc(),info.getJftRate());
        JSONObject result = ysPayOldService.jftPay(order, info.getJftMerc(), info.getJftChannel());
        order.setPayData(result.getString("payData"));
        baseMapper.insert(order);
        JSONObject payData = result.getJSONObject("payData");
        payData.put("orderNumber",order.getOrderNumber());
        return ResultGenerator.genSuccessResult("操作成功",payData);
    }

    /**
     * 校验结算人信息
     */
    private JftReceiptInfo checkMercInfo(JftPayDataDTO dto) {
        JftReceiptInfo info = jriMapper.getByToken(dto.getTk());
        JftBankCard bankCard = jftBankCardService.getByUserId(info.getUserId());
        boolean flag = !dto.getCName().equals(bankCard.getBankHolder()) || !dto.getCPhone().equals(bankCard.getPhone());
        MsgException.check(flag,"收款人名称或手机号信息不匹配，请核对！");
        JftMerchantRate jftRate = jftMerchantRateService.getRateByUserId(info.getUserId());
        MsgException.checkNull(jftRate,"商户费率配置异常");
        JftMercBaseInfo jfrMerc = jftMercBaseInfoService.getMercBaseInfo(info.getUserId());
        MsgException.checkNull(jfrMerc,"商户信息异常");
        JftMercPaymentChannel jftChannel = jftMercPaymentChannelService.getByUserId(info.getUserId());
        MsgException.checkNull(jftChannel,"进件信息异常");
        List<RiskBlacklist> list = riskBlacklistMapper.getByUserId(info.getUserId());
        MsgException.check(!list.isEmpty(),"黑名单用户，不允许使用该功能");
        info.setJftRate(jftRate);
        info.setJftMerc(jfrMerc);
        info.setJftChannel(jftChannel);
        return info;
    }

    /**
     * 计算手续费
     * @param receiptOrder
     */
    private void calcOrderFee(JftReceiptOrder receiptOrder) {
        BigDecimal channelRate = Constant.DEFAULT_JFT_COST_RATE.divide(BigDecimal.valueOf(10000));
        BigDecimal mercRate = BigDecimal.valueOf(receiptOrder.getRate()).divide(BigDecimal.valueOf(10000));
        BigDecimal channelFee = channelRate.multiply(receiptOrder.getAmount()).setScale(2,BigDecimal.ROUND_HALF_UP);
        BigDecimal mercFee = mercRate.multiply(receiptOrder.getAmount()).setScale(2,BigDecimal.ROUND_HALF_UP);
        BigDecimal profitFee = mercRate.subtract(channelRate).multiply(receiptOrder.getAmount()).setScale(2,BigDecimal.ROUND_DOWN);
        receiptOrder.setChannelFee(channelFee);
        receiptOrder.setMercFee(mercFee);
        receiptOrder.setProfitFee(profitFee);
    }

    @Override
    public Page<JftReceiptOrderVO> pageData(Page<JftReceiptOrderVO> page, JftReceiptOrderDTO order) {
        return baseMapper.pageData(page,order);
    }
}
