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

import cn.hutool.core.date.DatePattern;
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.params.yspay.YspayIsvParams;
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.yspay.model.ReqMethod;
import com.jeequan.jeepay.thirdparty.channel.yspay.utils.YspayKit;
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.ArrayList;
import java.util.Date;
import java.util.List;

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

    @Autowired
    private ConfigContextQueryService configContextQueryService;

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

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

    /**
     *
     * @param applyment
     * @param mchRq
     * @return
     */
    @Override
    public ChannelRetMsg appidAndPath(MchApplyment applyment, ChannelMchRq mchRq) {
        ReqMethod.Method method = ReqMethod.Method.APPID_ADD_OR_UPDATE;
        JSONObject bizData = new JSONObject();
        //默认配置银联
        bizData.put("channelId","CUPS_WECHAT");
        bizData.put("mercId",applyment.getChannelMchNo());
        if(ChannelMchRq.Type.PATH.getType().equals(mchRq.getType())){
            bizData.put("payAuthPath",mchRq.getJsapiPath());
            method = ReqMethod.Method.AUTH_PATH_ADD;
        }else if(ChannelMchRq.Type.PUBLIC.getType().equals(mchRq.getType())){
            bizData.put("jsPayRelatedAppId",mchRq.getAppid());
        }else{
            bizData.put("appletId",mchRq.getAppid());
        }

        YspayIsvParams yspayIsvParams = (YspayIsvParams) configContextQueryService.queryIsvParams(applyment);

        JSONObject respBizData = YspayKit.reqV3(method, yspayIsvParams, bizData);
        ChannelRetMsg retMsg = new ChannelRetMsg();
        retMsg.setChannelBizData(respBizData);
        retMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
        return retMsg;
    }

    @Override
    public List<JSONObject> querySettleInfo(ChannelSettleRq settleRq, String isvNo, YspayIsvParams isvParams) {
        super.preSettleCheck(settleRq);
        ReqMethod.Method method = ReqMethod.Method.QUERY_SETTLE;
        JSONObject bizData = new JSONObject();
        if(settleRq.getMercNos() != null && !settleRq.getMercNos().isEmpty()){
            bizData.put("mercIds",settleRq.getMercNos());
        }
        if(StringUtils.isNotBlank(settleRq.getMercNo())){
            bizData.put("mercId",settleRq.getMercNo());
        }
        if(StringUtils.isNotEmpty(settleRq.getBillNo())){
            bizData.put("stlBillNo",settleRq.getBillNo());
        }else{
            bizData.put("pageNum",settleRq.getPage());
            bizData.put("pageSize",settleRq.getSize());
            if(settleRq.getStartDate() != null){
                bizData.put("startFactPayDate",DateUtil.format(settleRq.getStartDate(), DatePattern.PURE_DATE_PATTERN));
            }
            if(settleRq.getEndDate() != null){
                bizData.put("endFactPayDate", DateUtil.format(settleRq.getEndDate(), DatePattern.PURE_DATE_PATTERN));
            }
        }
        JSONObject respBizData = YspayKit.reqV3(method, isvParams, bizData);
        JSONArray infos = respBizData.getJSONArray("infos");
        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("stlBillNo"));
            data.put("isvNo", isvNo);
            data.put("accountNo",itemData.getString("accountNo"));
            data.put("accountName",itemData.getString("accountName"));
            data.put("settleType","D1");
            if(StringUtils.isNotBlank(itemData.getString("stlAmt"))){
                long stlAmt = itemData.getBigDecimal("stlAmt").multiply(BigDecimal.valueOf(100)).longValue();
                data.put("settleAmt",stlAmt);
            }
//            if(StringUtils.isNotBlank(itemData.getString("mercServiceAmt"))){
//                long feeAmt = itemData.getBigDecimal("mercServiceAmt").multiply(BigDecimal.valueOf(100)).longValue();
//                data.put("fee",feeAmt);
//            }
            SettleState payState = SettleState.getVal(itemData.getString("payState"));
            switch (payState){
                case PAY_SUCCESS:
                    data.put("state", SettleInfo.SUCCESS);
                    break;
                case PAY_PROGRESS:
                    data.put("state", SettleInfo.PROGRESS);
                    break;
                case PAY_FAIL:
                    data.put("state", SettleInfo.FAIL);
                    break;
                case PAY_ACCOUNT_FAIL:
                    data.put("state", SettleInfo.FAIL);
                    break;
                case PAY_SUSPEND:
                    data.put("state", SettleInfo.SUSPEND);
                    break;
                case PAY_FREEZE:
                    data.put("state", SettleInfo.FREEZE);
                    break;
                case PAY_TICKET:
                    data.put("state", SettleInfo.TICKET);
                    break;
                default:
                    data.put("state", SettleInfo.WAIT);
                    break;
            }
            data.put("channelState",payState.getState());
            data.put("channelCode",itemData.getString("retrunCode"));
            data.put("remark",itemData.getString("retrunMsg"));
            data.put("bankName",itemData.getString("bankName"));
            String payDate = itemData.getString("payDate");
            if(StringUtils.isNotBlank(payDate)){
                data.put("settleDate",DateUtil.format(DateUtil.parse(payDate,DatePattern.PURE_DATE_PATTERN),DatePattern.NORM_DATE_PATTERN));
            }
            Long payStateTime = itemData.getLong("payStateTime");
            data.put("settleTime",new Date(payStateTime));
            data.put("extra", itemData.toString());
            result.add(data);
        });
        return result;
    }

    @Getter
    @AllArgsConstructor
    public enum SettleState{

        PAY_WAIT_ACCOUNT("01","待记账"),

        PAY_PROGRESS("02","付款中"),

        PAY_SUCCESS("00","付款成功"),

        PAY_CANCEL("03","作废"),

        PAY_FAIL("04","付款失败"),

        PAY_NO("05","无需付款"),

        PAY_SUSPEND("06","暂缓"),

        PAY_FREEZE("07","冻结"),

        PAY_ACCOUNT_FAIL("08","记账失败"),

        PAY_WAIT("09","等待付款"),

        PAY_TICKET("10","已退票");

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