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

import com.alibaba.fastjson.JSON;
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.MchApplyment;
import com.jeequan.jeepay.core.entity.MchModifyApplyment;
import com.jeequan.jeepay.core.entity.MchSubInfo;
import com.jeequan.jeepay.core.exception.ResponseException;
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchApplymentNotifyService;
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchModifyApplymentService;
import com.jeequan.jeepay.db.entity.MchModifyApplymentEntity;
import com.jeequan.jeepay.db.entity.MchSubInfoEntity;
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.channel.IsvFactory;
import com.jeequan.jeepay.thirdparty.channel.sxfpay.model.ApplymentNotify;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

@Slf4j
@Service("sxfpayIsvmchApplymentNotifyService")
public class SxfpayIsvmchApplymentNotifyService implements IIsvmchApplymentNotifyService {

    @Autowired
    private RequestKitBean requestKitBean;

    @Autowired
    private MchSubInfoService mchSubInfoService;

    @Autowired
    private MchModifyApplymentService modifyApplymentService;

    @Autowired
    private MchInfoConverter mchInfoConverter;

    @Autowired
    private MchApplymentService mchApplymentService;

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

            return MutablePair.of(urlApplyId, applymentNotify);
        } catch (Exception e) {
            log.error("error", e);
            throw ResponseException.buildText("ERROR");
        }
    }

    private void handleModifyApply(ApplymentNotify applymentNotify, com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
        String changeSysFlowId = applymentNotify.getApplicationId();

        MchModifyApplyment modifyApplyment = getModifyApplymentByChannelApplyNo(changeSysFlowId);

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

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

        // 其他状态统一定为驳回
        if ("05".equals(applymentNotify.getTaskStatus())) { // 变更成功
            handleSuccessfulChange(modifyApplyment, mchApplyment, isvmchModifyApplymentService);
        } else {
            handleRejectedState(modifyApplyment, applymentNotify.getSuggestion());
        }
    }

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

        MutablePair<com.jeequan.jeepay.core.entity.MchApplyment, ResponseEntity> result = new MutablePair<>();

        if (ApplymentNotify.TASK_TYPE_INCOME.equals(applymentNotify.getTaskType())) {
            // 进件
            if ("1".equals(applymentNotify.getTaskStatus())) {
                MchApplyment resultMchApplyment = new MchApplyment();
                resultMchApplyment.setApplyId(mchApplyment.getApplyId());
                resultMchApplyment.setState(MchApplyment.STATE_SUCCESS);
                resultMchApplyment.setChannelMchNo(applymentNotify.getMno());
                result.left = resultMchApplyment;
                result.right = retOk(null);

                // 收集子商户信息
                collSubMerchInfo(mchApplyment, applymentNotify);

                return result;
            }

            // 驳回
            if ("2".equals(applymentNotify.getTaskStatus())) {
                MchApplyment resultMchApplyment = new MchApplyment();
                resultMchApplyment.setApplyId(mchApplyment.getApplyId());
                resultMchApplyment.setState(MchApplyment.STATE_REJECT_WAIT_MODIFY);
                resultMchApplyment.setApplyErrorInfo("[" + applymentNotify.getSuggestion() + "]");
                result.left = resultMchApplyment;
                result.right = retOk(null);

                return result;
            }
        }

        if (ApplymentNotify.TASK_TYPE_MODIFY.equals(applymentNotify.getTaskType())) {
            handleModifyApply(applymentNotify, mchApplyment);
        }

        return null;
    }

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

    /**
     * 收集子商户信息
     * @param mchApplyment
     * @param applymentNotify
     */
    public void collSubMerchInfo(MchApplyment mchApplyment, ApplymentNotify applymentNotify) {
        List<ApplymentNotify.Repo> repoInfo = applymentNotify.getRepoInfo();
//        List<MchSubInfoEntity> subInfoList = new ArrayList<>();
        for (ApplymentNotify.Repo repo : repoInfo) {
            MchSubInfoEntity item = new MchSubInfoEntity();
            item.setSubMchType(repo.getChildNoType());
            item.setSubMchId(repo.getChildNo());
            item.setStatus(repo.getRepoStatus());
            item.setChannelMchNo(applymentNotify.getMno());
            item.setChannelId(repo.getChannelId());
            item.setRemark(repo.getErrMessage());
            item.setAuthStatus(MchSubInfo.AUTH_STATUS_UNAUTHORIZED);
            // TODO 随行付没有银联和网联的标识
            item.setSubMchWay("SXF");
            item.setMainUse(1);
            item.setExt(((JSONObject) JSON.toJSON(repo)));
            item.setMchApplyId(mchApplyment.getApplyId());
            //TODO 防止重复插入导致报错
            try {
                mchSubInfoService.save(item);
            }catch (DuplicateKeyException e){
            }
//            subInfoList.add(item);
        }
//        mchSubInfoService.saveBatch(subInfoList);
    }

    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;
            default:
                mchModifyPair = new MutablePair<>(modifyApplyment, mchApplyment);
        }

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

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

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

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

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

    @Override
    public ResponseEntity<?> retOk(Object params) {
        JSONObject param = new JSONObject();
        param.put("code", "success");
        param.put("msg", "成功");

        return IIsvmchApplymentNotifyService.super.retOk(param);
    }
}
