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

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.exception.BizException;
import com.jeequan.jeepay.core.model.params.sxfpay.SxfpayIsvParams;
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.sxfpay.model.ReqMethod;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * TODO
 * @author crystal
 * @date 2023/12/4 10:47
 */
@Service
@Slf4j
public class SxfpayMchApiService extends AbstractMchApiService<SxfpayIsvParams> {

    @Autowired
    private ConfigContextQueryService configContextQueryService;

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

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

    /**
     * 配置微信相关参数
     * @param applyment
     * @param mchRq
     * @return
     */
    @Override
    public ChannelRetMsg appidAndPath(MchApplyment applyment, ChannelMchRq mchRq) {
        ReqMethod.Method method = ReqMethod.Method.MERCHANT_WX_CONF;
        JSONObject bizData = new JSONObject();
        bizData.put("mno",applyment.getChannelMchNo());
        bizData.put("subMchId", mchRq.getSubMchNo());
        if(ChannelMchRq.Type.PATH.getType().equals(mchRq.getType())){
            bizData.put("type","03");
            bizData.put("jsapiPath",mchRq.getJsapiPath());
        }else{
            bizData.put("type","01");
            bizData.put("subAppid",mchRq.getAppid());
            if(ChannelMchRq.Type.PUBLIC.getType().equals(mchRq.getType())){
                bizData.put("accountType","00");
            }else {
                bizData.put("accountType","01");
            }
        }
        SxfpayIsvParams isvParams = (SxfpayIsvParams) configContextQueryService.queryIsvParams(applyment);
        JSONObject respBizData = SxfpayKit.reqApi(method, isvParams, bizData);
        String bizCode = respBizData.getString("bizCode");
        String bizMsg = respBizData.getString("bizMsg");
        ChannelRetMsg retMsg = new ChannelRetMsg();
        retMsg.setChannelBizData(respBizData);
        retMsg.setChannelErrCode(bizCode);
        retMsg.setChannelErrMsg(bizMsg);
        retMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
        if(!SxfpayKit.SUCCESS_CODE.equals(bizCode)){
            throw new BizException(bizMsg);
        }
        return retMsg;
    }

    /**
     * 查询结算信息
     * @param settleRq
     * @param isvNo
     * @param isvParams
     * @return
     */
    @Override
    public List<JSONObject> querySettleInfo(ChannelSettleRq settleRq, String isvNo, SxfpayIsvParams isvParams) {
        JSONObject bizData = new JSONObject();
        bizData.put("mno",settleRq.getMercNo());
        if(StringUtils.isNotBlank(settleRq.getBillNo())){
            bizData.put("serialNo",settleRq.getBillNo());
        }else{
            bizData.put("queryTime",DateUtil.format(settleRq.getStartDate(),DatePattern.PURE_DATE_PATTERN));
        }
        JSONObject respBizData = SxfpayKit.reqApi(ReqMethod.Method.SETTLE_QUERY, isvParams, bizData);
        JSONArray infos = respBizData.getJSONArray("settleInfo");
        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("serialNo"));
            data.put("isvNo", isvNo);
            data.put("accountNo",itemData.getString("settleBnkNo"));
            data.put("accountName",itemData.getString("settleAccountNm"));
            if(StringUtils.isNotBlank(itemData.getString("amount"))){
                long stlAmt = itemData.getBigDecimal("amount").multiply(BigDecimal.valueOf(100)).longValue();
                data.put("settleAmt",stlAmt);
            }
//            if(StringUtils.isNotBlank(itemData.getString("fee"))){
//                long feeAmt = itemData.getBigDecimal("fee").multiply(BigDecimal.valueOf(100)).longValue();
//                data.put("fee",feeAmt);
//            }
            SettleState settleStatus = SettleState.getVal(itemData.getString("settleStatus"));
            switch (settleStatus){
                case SUCCESS:
                    data.put("state", SettleInfo.SUCCESS);
                    break;
                case PAYING:
                    data.put("state", SettleInfo.PROGRESS);
                    break;
                case TICKET:
                    data.put("state", SettleInfo.TICKET);
                    break;
                case WAIT:
                    data.put("state", SettleInfo.WAIT);
                    break;
                default:
                    data.put("state", SettleInfo.FAIL);
                    break;
            }
            data.put("channelState",settleStatus.getState());
            String remark = StringUtils.isNotEmpty(itemData.getString("refReason")) ? itemData.getString("refReason") : settleStatus.getDesc();
            data.put("remark",remark);
            data.put("bankName",itemData.getString("settleLbnk"));
            String settleTime = itemData.getString("settleTime");
            if(StringUtils.isNotEmpty(settleTime)){
                DateTime settle = DateUtil.parse(settleTime, DatePattern.PURE_DATETIME_PATTERN);
                data.put("settleDate",DateUtil.format(settle,DatePattern.NORM_DATE_PATTERN));
                data.put("settleTime",settle);
            }else{
                data.put("settleTime",new Date());
            }
            data.put("extra", itemData.toString());
            result.add(data);
        });
        return result;
    }

    @Getter
    @AllArgsConstructor
    public enum SettleState{

        SUCCESS("S","付款成功"),

        WAIT("I","待付款"),

        FAIL("F","付款失败"),

        PAYING("P","付款中"),

        EXPRIE("N","失效"),

        TICKET("R","退票");

        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 WAIT;
        }
    }
}
