package com.jeequan.jeepay.thirdparty.channel.flpay;

import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.CashoutRecord;
import com.jeequan.jeepay.core.exception.ChannelException;
import com.jeequan.jeepay.core.model.DBPaymentConfig;
import com.jeequan.jeepay.core.model.df.Account;
import com.jeequan.jeepay.core.model.df.PaymentSign;
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.core.utils.AmountUtil;
import com.jeequan.jeepay.db.entity.AccountFundInfo;
import com.jeequan.jeepay.db.entity.AccountInfo;
import com.jeequan.jeepay.service.impl.AccountInfoService;
import com.jeequan.jeepay.thirdparty.channel.flpay.model.ReqMethod;
import com.jeequan.jeepay.thirdparty.channel.AbstractRepayApiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Locale;

/**
 * TODO
 * 福禄打款
 * @author crystal
 * @date 2024/3/25 10:38
 */
@Service
@Slf4j
public class FlpayRepayApiService extends AbstractRepayApiService {

    @Autowired
    private AccountInfoService accountInfoService;

    @Override
    public String getIfCode() {
        return CS.IF_CODE.FLPAY;
    }

    /**
     * 是否需要签约
     * @return
     */
    @Override
    public boolean isSign() {
        return true;
    }

    @Override
    public void preCheck(String mchNo,byte accountType,Long changeAmt) {
        this.checkAccountBalance(mchNo,accountType,changeAmt);
    }

    /**
     * 查询账户余额
     * @param mchNo 用户号
     * @param accountType 账户类型
     * @return
     */
    @Override
    public Account queryAccountBalance(String mchNo, byte accountType) {
        AccountInfo accountInfo = accountInfoService.getAccountInfo(mchNo, accountType);
        return new Account(accountInfo.getBalacne(),accountInfo.getFreeze());
    }

    /**
     * 签约正常 签约状态(0-待处理 1-校验失败 2-待签约 3-签约成功 4-校验错误)
     * @param sign
     * @param config
     * @return
     */
    @Override
    public ChannelRetMsg sign(PaymentSign sign, DBPaymentConfig config) {
        JSONObject bizData = new JSONObject();
        bizData.put("userName",sign.getUserName());
        bizData.put("idCard",sign.getIdCard().toUpperCase(Locale.ROOT));
        bizData.put("mobile",sign.getMobile());
        JSONObject respBizData = FlKit.reqApi(ReqMethod.Method.SIGN, config, bizData);
        Integer signStatus = respBizData.getInteger("signStatus");
        switch (signStatus){
            case 3:
                return ChannelRetMsg.confirmSuccess(respBizData.getString("peopleId"));
        }
        return ChannelRetMsg.confirmFail(null,respBizData.getString("failReason"));
    }

    /**
     * 签约结果查询
     * @param sign
     * @param config
     * @return
     */
    @Override
    public ChannelRetMsg querySign(PaymentSign sign, DBPaymentConfig config) {
        JSONObject bizData = new JSONObject();
        bizData.put("userName",sign.getUserName());
        bizData.put("idCard",sign.getIdCard().toUpperCase(Locale.ROOT));
        JSONObject respBizData = FlKit.reqApi(ReqMethod.Method.SIGN_QUERY, config, bizData);
        Integer signStatus = respBizData.getInteger("signStatus");
        switch (signStatus){
            case 3:
                return ChannelRetMsg.confirmSuccess(respBizData.getString("peopleId"));
        }
        return ChannelRetMsg.confirmFail(null,respBizData.getString("failReason"));
    }

    /**
     * 付款
     * @return
     */
    @Override
    public ChannelRetMsg payment(CashoutRecord record,DBPaymentConfig config) {
        JSONObject bizData = new JSONObject();
        bizData.put("accountNumber",record.getSettAccountNo());
        bizData.put("afterTaxAmount", AmountUtil.convertCent2Dollar(AmountUtil.abs(record.getSettAmount())));
        String grantType = AccountFundInfo.WECHAT.equals(record.getSettAccountType()) ? "微信支付" : AccountFundInfo.ALIPAY == record.getSettAccountType() ? "支付宝" : "银行卡";
        bizData.put("grantType", grantType);
        bizData.put("idCard",record.getIdCard());
        bizData.put("outBizNo",record.getTransferOrderId());
        bizData.put("mobile",record.getBankPhone());
        bizData.put("transRemark","账户结算处理");
        bizData.put("remark",record.getAuditRemark());
        bizData.put("userName",record.getSettAccountName());
        bizData.put("notifyUrl",getNotifyUrl());
        try {
            JSONObject respBizData = FlKit.reqApi(ReqMethod.Method.PAYMENT, config, bizData);
            ChannelRetMsg channelRetMsg = ChannelRetMsg.waiting();
            channelRetMsg.setChannelOrderId(respBizData.getString("bizNo"));
            channelRetMsg.setChannelBizData(respBizData);
            return channelRetMsg;
        }catch (ChannelException e){
            throw ChannelException.sysError(e.getMessage());
        }catch (Exception e){
            return ChannelRetMsg.confirmFail(e.getMessage());
        }
    }

    /**
     * 付款结果查询
     * @param outBizNo 外部请求流水号
     * @param config
     * @return
     */
    @Override
    public ChannelRetMsg queryPayment(String outBizNo, DBPaymentConfig config) {
        JSONObject bizData = new JSONObject();
        bizData.put("outBizNo",outBizNo);
        try {
            JSONObject respBizData = FlKit.reqApi(ReqMethod.Method.PAYMENT_QUERY, config, bizData);
            String failCause = respBizData.getString("failCause");
            Integer auditStatus = respBizData.getInteger("auditStatus");
            Integer payStatus = respBizData.getInteger("payStatus");
            String payFailCause = respBizData.getString("payFailCause");
            ChannelRetMsg retMsg = ChannelRetMsg.waiting();
            retMsg.setChannelErrMsg(failCause);
            switch (auditStatus){
                case 2:
                    return retMsg;
            }
            retMsg.setChannelErrMsg(payFailCause);
            switch (payStatus){
                case 3:
                    return ChannelRetMsg.confirmSuccess(respBizData.getString("bizNo"));
            }
            return retMsg;
        }catch (ChannelException e){
            throw ChannelException.sysError(e.getMessage());
        }catch (Exception e){
            return ChannelRetMsg.confirmFail(e.getMessage());
        }
    }
}
