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

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
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.MchModifyApplyment;
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchApplymentNotifyService;
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchModifyApplymentService;
import com.jeequan.jeepay.core.model.params.lklspay.LklspayIsvParams;
import com.jeequan.jeepay.db.entity.MchApplyment;
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.thirdparty.channel.IsvFactory;
import com.jeequan.jeepay.thirdparty.channel.lklsb2bpay.Lklsb2bpayIsvmchApplymentNotifyService;
import com.jeequan.jeepay.thirdparty.channel.lklspay.model.LklTkReqMethod;
import com.jeequan.jeepay.thirdparty.channel.lklspay.util.LklspayConst;
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 org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;
import java.util.Optional;

@Slf4j
@Service("lklspayIsvmchApplymentNotifyService")
public class LklspayIsvmchApplymentNotifyService implements IIsvmchApplymentNotifyService {

    @Autowired
    private RequestKitBean requestKitBean;

    @Autowired
    private MchApplymentService mchApplymentService;

    @Autowired
    private MchModifyApplymentService modifyApplymentService;

    @Autowired
    private ConfigContextQueryService configContextQueryService;

    @Autowired
    private LklspayMchApplymentService lklspayMchApplymentService;

    @Autowired
    private Lklsb2bpayIsvmchApplymentNotifyService lklsb2bpayIsvmchApplymentNotifyService;

    @Autowired
    private MchInfoConverter mchInfoConverter;

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

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

        log.info("拉卡拉进件回调原始参数：{}", reqParamJSON);
        RSA rsa = SecureUtil.rsa(null, LklspayIsvParams.PUB_KEY);
        String decryptData = rsa.decryptStr(reqParamJSON.getString("data"), KeyType.PublicKey);
        log.info("拉卡拉进件回调解密参数: {}", decryptData);

        JSONObject bizJSON = JSON.parseObject(decryptData);

        String reviewRelatedId = bizJSON.getString(LklspayConst.REVIEW_RELATED_ID);
        String customerNo = bizJSON.getString(LklspayConst.CUSTOMER_NO);

        if (!ObjectUtils.isEmpty(customerNo)) {
            // 进件
            MchApplyment tbMchApplyment = mchApplymentService.getByOrderId(customerNo);
            if (tbMchApplyment != null) {
                return MutablePair.of(tbMchApplyment.getApplyId(), bizJSON);
            }
        }

        if (!ObjectUtils.isEmpty(reviewRelatedId)) {
            // 变更
            MchModifyApplymentEntity mchModifyApplyment = modifyApplymentService.getByOrderId(reviewRelatedId, CS.IF_CODE.LKLSPAY);
            if (mchModifyApplyment != null) {
                return MutablePair.of(mchModifyApplyment.getApplyId(), bizJSON);
            }
        }

        return null;
    }

    @Override
    public MutablePair<com.jeequan.jeepay.core.entity.MchApplyment, ResponseEntity> doNotify(HttpServletRequest request, Object params, com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
        if (CS.IF_CODE.LKLSB2BPAY.equals(mchApplyment.getIfCode())) {
            return lklsb2bpayIsvmchApplymentNotifyService.doNotify(request, params, mchApplyment);
        }

        JSONObject bizJSON = (JSONObject) params;

        LklspayIsvParams isvParams = ((LklspayIsvParams) configContextQueryService.queryIsvParams(mchApplyment));

        String reviewRelatedId = bizJSON.getString(LklspayConst.REVIEW_RELATED_ID);
        String customerNo = bizJSON.getString(LklspayConst.CUSTOMER_NO);

        if (!ObjectUtils.isEmpty(customerNo)) {
            // 进件回调处理
            return doAuditNotify(bizJSON, mchApplyment, isvParams);
        }

        if (!ObjectUtils.isEmpty(reviewRelatedId)) {
            // 变更回调处理
            return doModifyNotify(reviewRelatedId, mchApplyment, bizJSON);
        }

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

    public MutablePair<com.jeequan.jeepay.core.entity.MchApplyment, ResponseEntity> doAuditNotify(
            JSONObject bizJSON, com.jeequan.jeepay.core.entity.MchApplyment mchApplyment, LklspayIsvParams isvParams) {
        String status = bizJSON.getString("status");
        String remark = bizJSON.getString("remark");

        mchApplyment.setRemark(remark);

        // 进件
        if ("SUCCESS".equals(status)) {
            JSONObject param = new JSONObject();
            param.put("customerNo", mchApplyment.getChannelApplyNo());
            JSONObject respData = LklspayKit.applymentRequest(LklTkReqMethod.AUDIT_STATUS_GET, isvParams, param);

            JSONObject customer = respData.getJSONObject("customer");
            JSONArray customerFeeList = respData.getJSONArray("customerFee");
            String termId = null;
            // 将对应终端号下的终端id存下来
            for (int i = 0; i < customerFeeList.size(); i++) {
                JSONObject customerFee = customerFeeList.getJSONObject(i);
                String termNo = customerFee.getString("termNo");
                if (Objects.equals(termNo, customer.getString("termNo"))) {
                    termId = customerFee.getString("termId");
                    break;
                }
            }

            String externalCustomerNo = customer.getString("externalCustomerNo");
            mchApplyment.setChannelMchNo(externalCustomerNo);
            mchApplyment.setSuccResParameter(customer.toString());
            Optional.ofNullable(termId).ifPresent(t -> customer.put("termId", t));

            lklspayMchApplymentService.subMchColl(mchApplyment);
            // 进件通过
            mchApplyment.setState(com.jeequan.jeepay.core.entity.MchApplyment.STATE_SUCCESS);

            return MutablePair.of(mchApplyment, retOk(null));
        } else {
            mchApplyment.setApplyErrorInfo(remark);
        }

        String[] failStatusList = new String[]{
                "COMMIT_FAIL",
                "FAILURE",
                "INNER_CHECK_REJECTED"
        };

        if (ArrayUtil.contains(failStatusList, status)) {
            mchApplyment.setState(com.jeequan.jeepay.core.entity.MchApplyment.STATE_REJECT_WAIT_MODIFY);
        }

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

    public MutablePair<com.jeequan.jeepay.core.entity.MchApplyment, ResponseEntity> doModifyNotify(
            String reviewRelatedId, com.jeequan.jeepay.core.entity.MchApplyment mchApplyment, JSONObject bizJSON) {
        // 变更
        MchModifyApplymentEntity mchModifyApplyment = modifyApplymentService.getByOrderId(reviewRelatedId, CS.IF_CODE.LKLSPAY);

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

        if (!Objects.equals(mchModifyApplyment.getState(), MchApplyment.STATE_WAIT_SIGN)
                && !Objects.equals(mchModifyApplyment.getState(), MchApplyment.STATE_AUDITING)) {
            // 已经处理过，直接返回
            return MutablePair.of(null, retOk(null));
        }

        handleModifyApply(bizJSON, mchApplyment);

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

    private void handleModifyApply(JSONObject bizJSON, com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
        String reviewPass = bizJSON.getString("reviewPass");
        String reviewRelatedId = bizJSON.getString("reviewRelatedId");
        String reviewResult = bizJSON.getString("reviewResult");

        MchModifyApplyment modifyApplyment = getModifyApplymentByChannelApplyNo(reviewRelatedId);

        IIsvmchModifyApplymentService isvmchModifyApplymentService = IsvFactory.getIsvMchModifyApplymentService(CS.IF_CODE.LKLSPAY);

        if (mchApplyment.getState() == MchApplyment.STATE_SUCCESS) {
            // 已经变更完成，直接退出
            return;
        }


        if (reviewPass.equals(LklspayConst.EDIT_PASS)) {
            // 变更成功
            handleSuccessfulChange(modifyApplyment, mchApplyment, isvmchModifyApplymentService);
        } else {
            // 其他状态统一定为驳回
            handleRejectedState(modifyApplyment, reviewResult);
        }
    }

    private MchModifyApplyment getModifyApplymentByChannelApplyNo(String channelApplyNo) {
        LambdaQueryWrapper<MchModifyApplymentEntity> qWrapper = Wrappers.lambdaQuery();
        qWrapper.eq(MchModifyApplymentEntity::getChannelApplyNo, channelApplyNo);
        return mchInfoConverter.toModel(modifyApplymentService.getOne(qWrapper));
    }

    private void handleSuccessfulChange(MchModifyApplyment modifyApplyment, com.jeequan.jeepay.core.entity.MchApplyment mchApplyment, IIsvmchModifyApplymentService isvmchModifyApplymentService) {
        MutablePair<MchModifyApplyment, com.jeequan.jeepay.core.entity.MchApplyment> mchModifyPair;
        switch (modifyApplyment.getModifyApplyType()) {
            case MchModifyApplyment.MODIFY_TYPE_BASE:
                mchModifyPair = isvmchModifyApplymentService.localModifyBase(new MutablePair<>(modifyApplyment, mchApplyment));
                break;
            case MchModifyApplyment.MODIFY_TYPE_SETTLEMENT:
                mchModifyPair = isvmchModifyApplymentService.localModifySettlement(new MutablePair<>(modifyApplyment, mchApplyment));
                break;
            case MchModifyApplyment.MODIFY_TYPE_RATE:
                mchModifyPair = isvmchModifyApplymentService.localModifyRate(new MutablePair<>(modifyApplyment, mchApplyment));
                break;
            case MchModifyApplyment.MODIFY_TYPE_SETTLEMENT_TYPE:
                mchModifyPair = isvmchModifyApplymentService.localModifySettlementType(new MutablePair<>(modifyApplyment, mchApplyment));
                break;
            default:
                mchModifyPair = new MutablePair<>(modifyApplyment, mchApplyment);
        }

        updateModificationState(mchModifyPair.getLeft(), mchModifyPair.getRight());
    }

    private void handleRejectedState(MchModifyApplyment modifyApplyment, String note) {
        MchModifyApplymentEntity result = new MchModifyApplymentEntity();
        result.setModifyApplyId(modifyApplyment.getModifyApplyId());
        result.setApplyErrorInfo("[" + note + "]");
        result.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
        modifyApplymentService.updateById(result);
    }

    private void updateModificationState(MchModifyApplyment modifyApplyment, com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
        MchModifyApplymentEntity dbEntity = mchInfoConverter.toDbEntity(modifyApplyment);
        MchApplyment dbEntity1 = mchInfoConverter.toDbEntity(mchApplyment);

        // 状态变更就更新
        if (!modifyApplyment.getState().equals(mchApplyment.getState())) {
            modifyApplymentService.updateById(dbEntity);

            // 变更成功就更新商户数据
            if (modifyApplyment.getState() == MchApplyment.STATE_SUCCESS) {
                mchApplymentService.updateById(dbEntity1);
            }
        }
    }
}
