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

import cn.hutool.core.text.CharSequenceUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.converter.MchInfoConverter;
import com.jeequan.jeepay.core.beans.RequestKitBean;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchApplyment;
import com.jeequan.jeepay.core.entity.MchModifyApplyment;
import com.jeequan.jeepay.core.entity.MchSubInfo;
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchApplymentNotifyService;
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
import com.jeequan.jeepay.db.entity.MchModifyApplymentEntity;
import com.jeequan.jeepay.service.impl.MchApplymentService;
import com.jeequan.jeepay.service.impl.MchModifyApplymentService;
import com.jeequan.jeepay.service.impl.MchSubInfoService;
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;

@Slf4j
@Service
public class DgpayIsvmchApplymentNotifyService implements IIsvmchApplymentNotifyService {

    @Autowired
    private RequestKitBean requestKitBean;

    @Autowired
    private ConfigContextQueryService configContextQueryService;

    @Autowired
    private MchApplymentService mchApplymentService;

    @Autowired
    private MchInfoConverter mchInfoConverter;

    @Autowired
    private MchSubInfoService mchSubInfoService;

    @Autowired
    private MchModifyApplymentService modifyApplymentService;

    @Override
    public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlApplyId) {
        JSONObject reqParamJSON = requestKitBean.getReqParamJSON();

        JSONObject data = reqParamJSON.getJSONObject("data");

        String applyNo = data.getString("apply_no");

        com.jeequan.jeepay.db.entity.MchApplyment mchApplyment = mchApplymentService.getByOrderId(applyNo);
        if (mchApplyment == null) {
            // 此时查询变更的申请单
            MchModifyApplymentEntity mchModifyApplyment = modifyApplymentService.getByOrderId(applyNo, CS.IF_CODE.DGPAY);
            if (mchModifyApplyment == null) {
                return MutablePair.of(null, data);
            }
            mchApplyment = mchApplymentService.getByChannelMchNo(mchModifyApplyment.getChannelMchNo());
        }

        if (mchApplyment == null) {
            return MutablePair.of(null, data);
        }

        DgpayIsvParams isvParams = (DgpayIsvParams) configContextQueryService.queryIsvParams(mchInfoConverter.toModel(mchApplyment));


        boolean verify = DgPayKit.verify(data.toJSONString(), isvParams.getRsaPublicKey(), reqParamJSON.getString("sign"));
        if (!verify) {
            log.info("斗拱支付回调参数验签不通过");
        }

        return MutablePair.of(mchApplyment.getApplyId(), data);
    }

    @Override
    public MutablePair<MchApplyment, ResponseEntity> doNotify(HttpServletRequest request, Object params, MchApplyment mchApplyment) {

        JSONObject response = ((JSONObject) params);

        JSONObject resData = response.getJSONObject("data");
        String notifyType = resData.getString("notify_type");

        if (response.getString("apply_no").equals(mchApplyment.getChannelApplyNo())) {
            // 入网回调
            if (CharSequenceUtil.isEmpty(notifyType)) {
                applyResult(resData, mchApplyment);
            } else {
                // 报备回调
                reportResult(resData, mchApplyment);

                return MutablePair.of(mchApplyment, retOk("RECV_ORD_ID_" + resData.getString("ord_id")));
            }
        } else {
            MchModifyApplymentEntity mchModifyApplyment = modifyApplymentService.getByOrderId(response.getString("apply_no"), CS.IF_CODE.DGPAY);
            // 变更回调
            changeResult(resData, mchInfoConverter.toModel(mchModifyApplyment));
        }

        return MutablePair.of(mchApplyment, retOk(null));
    }

    private void changeResult(JSONObject resData, MchModifyApplyment modifyApplyment) {
        String auditStatus = resData.getString("audit_status");
        String auditDesc = resData.getString("audit_desc");

        MchModifyApplymentEntity result = new MchModifyApplymentEntity();
        result.setModifyApplyId(modifyApplyment.getModifyApplyId());
        if ("Y".equals(auditStatus)) {
            // 变更成功
            modifyApplymentService.localModify(modifyApplyment);
        } else if ("N".equals(auditStatus) || "F".equals(auditStatus)) {
            // 变更失败
            result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
            result.setApplyErrorInfo("[" + auditDesc + "]");

            modifyApplymentService.updateById(result);
        }
    }

    private void reportResult(JSONObject resData, MchApplyment mchApplyment) {
        MchApplyment result = new MchApplyment();
        result.setApplyId(mchApplyment.getApplyId());
        String code = resData.getString("sub_resp_code");
        String notifyType = resData.getString("notify_type");
        String huifuId = resData.getString("huifu_id");

        if (!"00000000".equals(code)) {
            return;
        }

        MchSubInfo mchSubInfo = new MchSubInfo();
        mchSubInfo.setChannelMchNo(huifuId);
        mchSubInfo.setAuthStatus(MchSubInfo.AUTH_STATUS_UNAUTHORIZED);
        switch (notifyType) {
            case "W":
                mchSubInfo.setSubMchType("WX");
                break;
            case "A":
                mchSubInfo.setSubMchType("ZFB");
                break;
            case "U":
                mchSubInfo.setSubMchType("BANK");
                break;
            default:
        }
        // 通知类型，没有则是申请单审核异步回调

        JSONArray regResultList = resData.getJSONArray("reg_result_list");

        if (regResultList == null || regResultList.isEmpty()) {
            return;
        }

        for (int i = 0; i < regResultList.size(); i++) {
            JSONObject item = regResultList.getJSONObject(i);

            MchSubInfo newEntity = mchInfoConverter.clone(mchSubInfo);
            newEntity.setExt(item);
            newEntity.setStatus(item.getString("business_stat"));
            newEntity.setSubMchId(item.getString("sub_mer_id"));
            newEntity.setChannelId(item.getString("pay_channel_id"));
            mchSubInfoService.save(mchInfoConverter.toDbEntity(newEntity));
        }
    }

    private void applyResult(JSONObject resData, MchApplyment mchApplyment) {
        MchApplyment result = new MchApplyment();
        result.setApplyId(mchApplyment.getApplyId());
        String code = resData.getString("sub_resp_code");

        if ("00000000".equals(code)) {
            return;
        }

        String auditStatus = resData.getString("audit_status");
        String auditDesc = resData.getString("audit_desc");
        // 通知类型，没有则是申请单审核异步回调

        if ("Y".equals(auditStatus)) {
            String huifuId = resData.getString("huifu_id");
            // 进件查询响应参数
            result.setApplyErrorInfo("[" + auditDesc + "]");
            result.setState(MchApplyment.STATE_SUCCESS);
            result.setChannelMchNo(huifuId);
            result.setSuccResParameter(resData.toString());
            mchApplymentService.updateById(mchInfoConverter.toDbEntity(result));
        } else if ("N".equals(auditStatus) || "F".equals(auditStatus)) {
            result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
            result.setApplyErrorInfo("[" + auditDesc + "]");
            mchApplymentService.updateById(mchInfoConverter.toDbEntity(result));
        }
    }

    @Override
    public ResponseEntity<?> retOk(Object params) {
        return ResponseEntity.ok("SUCCESS");
    }
}
