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

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchApplyment;
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
import com.jeequan.jeepay.core.model.params.ruipay.RyxpayIsvParams;
import com.jeequan.jeepay.core.model.rqrs.mch.ChannelMchRq;
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.core.model.rqrs.settle.ChannelSettleRq;
import com.jeequan.jeepay.db.entity.SettleInfo;
import com.jeequan.jeepay.thirdparty.channel.AbstractMchApiService;
import com.jeequan.jeepay.thirdparty.channel.ryxpay.model.PayRespEntity;
import com.jeequan.jeepay.thirdparty.channel.ryxpay.model.ReqMethod;
import com.jeequan.jeepay.thirdparty.channel.ryxpay.model.RyxAccessResp;
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * TODO
 * 瑞银信商户api服务类
 * @author crystal
 * @date 2023/12/4 10:47
 */
@Service
@Slf4j
public class RyxpayMchApiService extends AbstractMchApiService<RyxpayIsvParams> {

    @Autowired
    private ConfigContextQueryService configContextQueryService;

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

    @Override
    public boolean preCheck() {
        return true;
    }

    /**
     * 新增appid或者支付授权目录
     * @param applyment
     * @param mchRq
     * @return
     */
    @Override
    public ChannelRetMsg appidAndPath(MchApplyment applyment, ChannelMchRq mchRq) {
        ReqMethod.ServiceCode method = ReqMethod.ServiceCode.SUB_APPID;
        JSONObject bizData = new JSONObject();
        bizData.put("merchantCode",applyment.getChannelMchNo());
        if(ChannelMchRq.Type.PATH.getType().equals(mchRq.getType())){
            bizData.put("jsapiPath",mchRq.getJsapiPath());
            method =  ReqMethod.ServiceCode.JSAPI_PATH;
        }else{
            bizData.put("subAppid",mchRq.getAppid());
        }
        RyxpayIsvParams isvParams = (RyxpayIsvParams) configContextQueryService.queryIsvParams(applyment);
        PayRespEntity response = RyxpayKit.payReqApi(method, isvParams, bizData, null, null);
        ChannelRetMsg retMsg = new ChannelRetMsg();
        retMsg.setChannelBizData(response.getData());
        String respType = response.getRespType();
        retMsg.setChannelErrCode(response.getRespCode());
        retMsg.setChannelErrMsg(response.getRespMsg());
        if(RyxpayKit.RESP_BIZ_SUCCESS.equals(respType)){
            retMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
        }else{
            retMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
        }
        return retMsg;
    }

    @Override
    public List<JSONObject> querySettleInfo(ChannelSettleRq settleRq, String isvNo, RyxpayIsvParams isvParams) {
        ReqMethod.Method method = ReqMethod.Method.MERCHANT_TODAY_SETTLE_QUERY;
        JSONObject bizData = new JSONObject();
        bizData.put("s_merInId",settleRq.getExtMchNo());
        if(StringUtils.isNotEmpty(settleRq.getTransDateScope())){
            method = ReqMethod.Method.MERCHANT_SETTLE_QUERY;
            String[] transDateScope = settleRq.getTransDateScope().split(SettleInfo.TRANS_SCOPE_DATE_SPLIT);
            bizData.put("s_tranDates",DateUtil.format(DateUtil.parse(transDateScope[0],DatePattern.NORM_DATE_PATTERN),DatePattern.PURE_DATE_PATTERN));
            bizData.put("s_tranDatee",DateUtil.format(DateUtil.parse(transDateScope[1],DatePattern.NORM_DATE_PATTERN),DatePattern.PURE_DATE_PATTERN));
            bizData.put("page",settleRq.getPage());
            bizData.put("rows",settleRq.getSize());
        }
        RyxAccessResp ryxAccessResp = RyxpayKit.auditReqApi(method, isvParams, bizData, null);
        JSONObject resultData = ryxAccessResp.getResult();
        JSONArray infos = resultData.getJSONArray("list");
        if(infos == null || infos.isEmpty()){
            return null;
        }
        List<JSONObject> result = new ArrayList<>(infos.size());
        infos.forEach(item -> {
            JSONObject itemData = ((JSONObject) item);
            JSONObject data = new JSONObject();
            //没有结算编号 根据参数生成一个编号
            data.put("billNo",itemData.getString("merId") + "_" + itemData.getString("settleType") + "_" + itemData.getString("settDate"));
            data.put("isvNo", isvNo);
            data.put("accountNo",itemData.getString("cardNo"));
            data.put("accountName",itemData.getString("cardName"));
            if(StringUtils.isNotBlank(itemData.getString("amt"))){
                long stlAmt = itemData.getBigDecimal("amt").multiply(BigDecimal.valueOf(100)).longValue();
                data.put("settleAmt",stlAmt);
            }
            SettleState payState = SettleState.getVal(itemData.getString("status"));
            switch (payState){
                case SUCCESS:
                    data.put("state", SettleInfo.SUCCESS);
                    break;
                case PROGRESS:
                    data.put("state", SettleInfo.PROGRESS);
                    break;
                case FAIL:
                    data.put("state", SettleInfo.FAIL);
                    break;
                default:
                    data.put("state", SettleInfo.WAIT);
                    break;
            }
            data.put("channelState",payState.getState());
            data.put("channelCode",itemData.getString("retrunCode"));
            data.put("remark",itemData.getString("failReason"));
            data.put("bankName",itemData.getString("bankName"));
            String settDate = itemData.getString("settDate");
            if(StringUtils.isNotBlank(settDate)){
                DateTime settleTime = DateUtil.parse(settDate, DatePattern.PURE_DATETIME_PATTERN);
                data.put("settleDate",DateUtil.format(settleTime,DatePattern.NORM_DATE_PATTERN));
                data.put("settleTime",settleTime);
            }
            data.put("extra", itemData.toString());
            result.add(data);
        });
        return result;
    }

    @Getter
    @AllArgsConstructor
    public enum SettleState{

        SUCCESS("出款成功","结算成功"),

        PROGRESS("出款中","付款中"),

        FAIL("出款失败","付款失败");

        private final String state;

        private final String desc;

        public static SettleState getVal(String state){
            SettleState[] values = values();
            for (SettleState val:values) {
                if(val.getState().equals(state)){
                    return val;
                }
            }
            return PROGRESS;
        }
    }

}
