package cn.pluss.platform.wx.impl;

import cn.pluss.platform.channel.MerchantAuditService;
import cn.pluss.platform.channel.MerchantCertService;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.mapper.MerchantChannelMapper;
import cn.pluss.platform.mapper.MerchantChannelStatusMapper;
import cn.pluss.platform.mapper.SubMerchantApplyOrderMapper;
import cn.pluss.platform.merchant.MerchantBaseInfoService;
import cn.pluss.platform.merchantChannelStatus.MerchantChannelStatusService;
import cn.pluss.platform.subMerchant.SubMerchantService;
import cn.pluss.platform.userApp.UserAppService;
import cn.pluss.platform.vo.WxCertInfoVO;
import cn.pluss.platform.wx.WxCertService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author DJH
 */
@Slf4j
@Service("wxCertService")
@RequiredArgsConstructor
public class WxCertServiceImpl implements WxCertService {

    @Autowired
    private MerchantBaseInfoService mbiService;

    @Autowired
    private MerchantCertService sxfCertService;

    @Autowired
    private MerchantCertService ysCertService;

    @Autowired
    private MerchantCertService ysCertV2Service;

    @Autowired
    private MerchantCertService ryxCertService;

    @Autowired
    private UserAppService userAppService;

    @Autowired
    private MerchantChannelStatusService mcsService;

    @Autowired
    private SubMerchantService smService;

    @Resource
    private MerchantChannelStatusMapper mcsMapper;

    @Resource
    private SubMerchantApplyOrderMapper applyOrderMapper;

    @Resource
    private MerchantChannelMapper mcMapper;

    @Autowired @Lazy
    private MerchantAuditService ryxMerchantAuditService;

    @Override
    public void wxCert(String userId, String merchantCode, Integer channelId) {
        merchantCode = paramCheck(userId, merchantCode);

        MerchantChannelStatus merchantChannelStatus = mcsMapper.getByMerchantCode(merchantCode, channelId);

        if (merchantChannelStatus == null) {
            throw new MsgException("无用户进件信息");
        }

        if (merchantChannelStatus.getChannel() == 3) {
            throw new MsgException("非随行付、银盛进件商户不支持该操作");
        }

        // 存在待处理的微信认证请求即不再次请求认证
        SubMerchantApplyOrder subMerchantApplyOrder = new SubMerchantApplyOrder()
                .setMerchantCode(merchantCode)
                .setChannelId(channelId)
                .setSubMchType("WX")
                .setStatus("0");
        SubMerchantApplyOrder existData = applyOrderMapper.selectOne(new QueryWrapper<>(subMerchantApplyOrder).isNotNull("applyNo").orderByDesc("createTime").last("limit 1"));
        if (existData != null) {
            throw new MsgException("当前微信认证状态不允许执行该操作");
        }

        subMerchantApplyOrder.setStatus("1");
        existData = applyOrderMapper.selectOne(new QueryWrapper<>(subMerchantApplyOrder).orderByDesc("createTime").last("limit 1"));
        if (existData != null && !StringUtils.isEmpty(existData.getApplyNo()) && StringUtils.isEmpty(existData.getInfoQrcode())) {
            // 存在已处理的微信认证, 并且微信认证不通过的, 将该数据撤销
            if (merchantChannelStatus.getChannel() == 1) {
                sxfCertService.wxReCert(merchantChannelStatus.getMerchantId(), merchantCode);
            }

            if (merchantChannelStatus.getChannel() == 4) {
                ysCertService.wxReCert(merchantChannelStatus.getMerchantId(), merchantCode);
            }
        } else {
            if (merchantChannelStatus.getChannel() == 1) {
                sxfCertService.wxCert(merchantChannelStatus.getMerchantId(), merchantChannelStatus.getMerchantCode());
            }

            if (merchantChannelStatus.getChannel() == 4) {
                ysCertService.wxCert(merchantChannelStatus.getMerchantId(), merchantCode);
            }
        }
    }

    @Override
    public void wxCertCancel(String userId, String merchantCode, Integer channelId) {
        merchantCode = paramCheck(userId, merchantCode);

        SubMerchantApplyOrder subMerchantApplyOrder = new SubMerchantApplyOrder().setMerchantCode(merchantCode).setChannelId(1).setSubMchType("WX").setStatus("1");
        subMerchantApplyOrder = applyOrderMapper.selectOne(new QueryWrapper<>(subMerchantApplyOrder).orderByDesc("createTime").last("limit 1"));
        if (subMerchantApplyOrder == null) {
            throw new MsgException("当前商户没有已发出的微信认证申请");
        }

        MerchantChannelStatus merchantChannelStatus = mcsMapper.getByMerchantCode(merchantCode, channelId);
        if (merchantChannelStatus == null) {
            throw new MsgException("无用户进件信息");
        }

        if (merchantChannelStatus.getChannel() == 1) {
            sxfCertService.wxCertCancel(merchantChannelStatus.getMerchantId(), subMerchantApplyOrder);
        } else {
            throw new MsgException("非随行付进件商户不支持该操作");
        }
    }

    private String paramCheck(String userId, String merchantCode) {
        if (StringUtils.isEmpty(merchantCode)) {
            if (StringUtils.isEmpty(userId)) {
                throw new MsgException("缺少必要参数");
            }

            UserApp userApp = new UserApp().setUserId(Long.parseLong(userId));
            userApp = userAppService.queryUserApp(userApp);

            if (userApp == null) {
                throw new MsgException("用户不存在");
            }

            return userApp.getMerchantCode();
        } else {
            return merchantCode;
        }
    }

    @Override
    public void wxCertApplyStatus(String merchantCode, Integer channelId) {
        MerchantChannelStatus mcs = mcsMapper.getByMerchantCode(merchantCode, channelId);

        SubMerchantApplyOrder applyOrder = new SubMerchantApplyOrder();
        applyOrder.setMerchantCode(merchantCode);
        applyOrder.setSubMchType("WX");
        applyOrder = applyOrderMapper.selectOne(Wrappers.query(applyOrder).orderByDesc("createTime").last("limit 1"));
        switch (channelId) {
            case 1:
                if (applyOrder != null) {
                    sxfCertService.wxCertResult(mcs.getMerchantId(), applyOrder.getApplyNo());
                }
                break;
            case 3:
                ryxCertService.wxCertResult(mcs.getMerchantId(), null);
                break;
            case 4:
                if (applyOrder != null) {
                    ysCertV2Service.wxCertResult(mcs.getMerchantId(), applyOrder.getApplyNo());
                }
                break;
            default:
                break;
        }
    }

    @Override
    public WxCertInfoVO wxCertInfo(String userId, String channelType) {
        MerchantBaseInfo mbi = mbiService.getMerchantBaseInfoByUserId(userId);
        MsgException.checkNull(mbi, "暂未进件");

        return wxCertInfo(mbi, channelType);
    }

    @Override
    public List<WxCertInfoVO> wxCertInfo(String userId) {
        MerchantBaseInfo mbi = mbiService.getMerchantBaseInfoByUserId(userId);
        MsgException.checkNull(mbi, "暂未进件");

        List<WxCertInfoVO> resultData = new ArrayList<>();
        WxCertInfoVO d1Data = wxCertInfo(mbi, Account.CHANNEL_TYPE_D1);
        resultData.add(d1Data);

        WxCertInfoVO d0Data = wxCertInfo(mbi, Account.CHANNEL_TYPE_D0);
        resultData.add(d0Data);

        return resultData;
    }

    private WxCertInfoVO wxCertInfo(MerchantBaseInfo mbi, String channelType) {
        if (StringUtils.isEmpty(channelType)) {
            MerchantChannelStatus mcs = mcsService.getValidData(mbi.getMerchantCode());
            if (Objects.equals(mcs.getChannel(), 4)) {
                channelType = "D0";
            } else {
                channelType = "D1";
            }
        }

        MerchantChannelStatus mcs = mcsService.getByMerchantCodeAndChannelType(mbi.getMerchantCode(), channelType);

        WxCertInfoVO result = WxCertInfoVO.empty(channelType);
        result.setMerchantCode(mbi.getMerchantCode());
        if (mcs == null || !(MerchantChannelStatus.AUDIT_STATUS_SUCCESS.equals(mcs.getStatus())
                || MerchantChannelStatus.AUDIT_STATUS_DATA_EDIT.equals(mcs.getStatus()))) {
            return result;
        }

        result.setChannelId(mcs.getChannel() + "");
        result.setMerchantId(mcs.getMerchantId());

        MerchantChannel mc = new MerchantChannel();
        mc.setId(mcs.getChannel());
        mc = mcMapper.selectOne(new QueryWrapper<>(mc));
        result.setChannelName(mc.getChannelName());
        result.setAltImgUrl(mc.getWxCertImg());

        SubMerchant subMerchant = new SubMerchant();
        subMerchant.setSubMchType("WX");
        subMerchant.setMerchantId(mcs.getMerchantId());

        List<SubMerchant> subMerchantList = smService.list(new QueryWrapper<>(subMerchant));
        // if (subMerchantList.isEmpty()) {
        //     smService.reqChannelSubMerchant(mcs);
        // }

        for (SubMerchant merchant : subMerchantList) {
            String subMchIdModel = merchant.getSubMchId();
            if (subMchIdModel == null) {
                continue;
            }

            String subMchId = subMchIdModel.split("_")[0];
            if (StringUtils.isNotEmpty(subMchId) && !subMchId.equals(subMerchant.getSubMchId())) {
                if (subMerchant.getSubMchId() == null) {
                    result.setWxSubMerchantId(subMchId);
                } else {
                    result.setWxSubMerchantId(result.getWxSubMerchantId() + "、" + subMerchant);
                }
            }
        }

        if (Objects.equals(mcs.getAuthorizationStatus(), MerchantChannelStatus.AUTHORIZATION_STATUS_AUTHORIZED)) {
            result.setStatus(SubMerchantApplyOrder.RES_STATUS_COMPLETE);
            return result;
        }

        SubMerchantApplyOrder applyOrder = new SubMerchantApplyOrder()
                .setMerchantCode(mbi.getMerchantCode())
                .setChannelId(mcs.getChannel())
                .setSubMchType("WX");
        applyOrder = applyOrderMapper.selectOne(new QueryWrapper<>(applyOrder).orderByDesc("createTime").last("limit 1"));
        if (applyOrder == null || !"1".equals(applyOrder.getStatus())) {
            // 没有发起认证的信息，或申请单未得到结果，手动获取对应通道下的申请单结果
            // wxCertApplyStatus(mcs.getMerchantCode(), mcs.getChannel());
            applyOrder = applyOrderMapper.selectOne(new QueryWrapper<>(applyOrder).orderByDesc("createTime").last("limit 1"));
        }

        if (applyOrder == null) {
            result.setStatus(SubMerchantApplyOrder.STATUS_NO_WX_AUDIT);
            return result;
        }

        result.setStatus(applyOrder.getResultStatus());
        result.setInfoQrcode(applyOrder.getInfoQrcode());
        result.setRemark(applyOrder.getRemark());

        // 未授权时查询商户的认证信息
        // mcsService.verifyWxAuthStatus(mcs);
        mcs = mcsService.getById(mcs.getId());
        if (Objects.equals(mcs.getAuthorizationStatus(), MerchantChannelStatus.AUTHORIZATION_STATUS_AUTHORIZED)) {
            result.setStatus(SubMerchantApplyOrder.RES_STATUS_COMPLETE);
        }

        if (SubMerchantApplyOrder.RES_STATUS_COMPLETE.equals(result.getStatus())) {
            return result;
        }

        if (SubMerchantApplyOrder.RES_STATUS_COMPLETE.equals(applyOrder.getResultStatus())) {
            result.setStatus(SubMerchantApplyOrder.RES_STATUS_SUCCESS);
            return result;
        }

        if ("0".equals(applyOrder.getStatus()) || "审核中".equals(applyOrder.getResultStatus())) {
            result.setStatus(SubMerchantApplyOrder.RES_STATUS_REVIEW);
            return result;
        }

        if (StringUtils.isEmpty(applyOrder.getInfoQrcode())) {
            result.setStatus(SubMerchantApplyOrder.RES_STATUS_FAILED);
        } else {
            result.setStatus(SubMerchantApplyOrder.RES_STATUS_SUCCESS);
        }

        return result;
    }

    @Override
    public void wxCertAuthStatus(String merchantCode, Integer channelId) {
        MerchantChannelStatus mcs = mcsMapper.getByMerchantCode(merchantCode, channelId);

        switch (channelId) {
            case 1:
                sxfCertService.wxCertAuthStatus(mcs.getMerchantId());
                break;
            case 3:
                ryxCertService.wxCertAuthStatus(mcs.getMerchantId());
                break;
            case 4:
                ysCertV2Service.wxCertAuthStatus(mcs.getMerchantId());
                break;
            default:
                break;
        }
    }
}
