package cn.pluss.platform.merchantChannelStatus.impl;

import cn.pluss.platform.SubMerchantApplyOrderService;
import cn.pluss.platform.channel.MerchProtocolService;
import cn.pluss.platform.channel.MerchantAuditService;
import cn.pluss.platform.channel.MerchantCertService;
import cn.pluss.platform.converter.Converter;
import cn.pluss.platform.entity.*;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.mapper.AccountMapper;
import cn.pluss.platform.mapper.MerchantChannelStatusMapper;
import cn.pluss.platform.merchant.MerchantBaseInfoService;
import cn.pluss.platform.merchantChannel.MerchantChannelService;
import cn.pluss.platform.merchantChannelStatus.MerchantChannelStatusService;
import cn.pluss.platform.notice.NoticeService;
import cn.pluss.platform.userApp.UserAppService;
import cn.pluss.platform.user.impl.GeneralPushUtil;
import cn.pluss.platform.vo.ChannelStatusVO;
import cn.pluss.platform.vo.UserNumVO;
import cn.pluss.platform.wx.WxTalkService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author DJH
 */
@Service
@Primary
public class MerchantChannelStatusServiceImpl extends ServiceImpl<MerchantChannelStatusMapper, MerchantChannelStatus> implements MerchantChannelStatusService {

    @Setter(onMethod_ = {@Autowired, @Lazy})
    private MerchantCertService ysCertV2Service;

    @Autowired
    private MerchantCertService sxfCertService;

    @Setter(onMethod_ = {@Autowired, @Lazy})
    private MerchantCertService ryxCertService;

    @Autowired @Lazy
    private MerchantAuditService ysAuditServiceV2;

    @Autowired
    @Qualifier("ysAuditServiceV2")
    @Lazy
    private MerchProtocolService ysMerchProtocolService;

    @Autowired @Lazy
    private MerchantChannelService merchantChannelService;

    @Setter(onMethod_ = {@Autowired, @Lazy})
    private NoticeService noticeService;

    @Setter(onMethod_ = {@Autowired, @Lazy})
    private SubMerchantApplyOrderService smaoService;

    @Setter(onMethod_ = {@Autowired, @Lazy})
    private MerchantBaseInfoService mbiService;

    @Autowired
    private WxTalkService wxTalkService;

    @Setter(onMethod_ = {@Autowired, @Lazy})
    private UserAppService userAppService;

    @Resource
    private AccountMapper accountMapper;

    @Autowired
    private GeneralPushUtil generalPushUtil;


    @Override
    public MerchantChannelStatus auditCheck(String merchantCode) {
        // 1、获取所有有效通道下
        LambdaQueryWrapper<MerchantChannel> qWrapper1 = Wrappers.lambdaQuery();
        qWrapper1.eq(MerchantChannel::getStatus, "1");
        List<MerchantChannel> validChannelList = merchantChannelService.list(qWrapper1);

        // 2、获取有效通道下该商户的所有进件记录
        List<Integer> channelList = new ArrayList<>();
        validChannelList.forEach( item -> channelList.add(item.getId()));
        LambdaQueryWrapper<MerchantChannelStatus> qWrapper2 = Wrappers.lambdaQuery();
        qWrapper2.eq(MerchantChannelStatus::getMerchantCode, merchantCode)
                .and(wrapper -> wrapper.in(MerchantChannelStatus::getChannel, channelList)
                        .or()
                        .isNull(MerchantChannelStatus::getChannel)
                );
        List<MerchantChannelStatus> channelStatusList = list(qWrapper2);

        int inChannelCount = 0;
        int auditSucCount = 0;
        for (MerchantChannelStatus item : channelStatusList) {
            MerchantChannelStatus.checkReqAudit(item);

            if (item.getChannel() != null) {
                inChannelCount++;
            }

            if (item.getStatus().equals(MerchantChannelStatus.AUDIT_STATUS_SUCCESS)) {
                auditSucCount++;
                continue;
            }

            if (item.getStatus().equals(MerchantChannelStatus.AUDIT_STATUS_REJECT)
                    || item.getStatus().equals(MerchantChannelStatus.AUDIT_STATUS_RESET)) {
                return item;
            }
        }

        // 当前D0、D1各只支持一个
        if (inChannelCount >= 2) {
            throw new MsgException("请勿重复进件");
        }

        if (auditSucCount == channelList.size()) {
            throw new MsgException("全部通道进件已通过，请勿重复进件");
        }

        return null;
    }

    @Override
    public MerchantChannelStatus getSxfMerchantStatusInfo(String merchantCode) {
        MerchantChannelStatus merchantChannelStatus = new MerchantChannelStatus().setMerchantCode(merchantCode).setChannel(1);
        merchantChannelStatus = baseMapper.selectOne(new QueryWrapper<>(merchantChannelStatus));
        return merchantChannelStatus;
    }

    @Override
    public void reqAudit(String merchantCode) {
        MerchantChannelStatus mcs = auditCheck(merchantCode);

        MerchantBaseInfo mbiEntity = mbiService.getMerchantBaseInfoByMerchantCode(merchantCode);

        if (mcs == null) {
            mcs = new MerchantChannelStatus();
            mcs.setMerchantCode(merchantCode);
        }

        // 小微要做单D0校验
        if ("1".equals(mbiEntity.getMerchantType())) {
            MerchantChannelStatus d1Merch = getByMerchantCodeAndChannelType(merchantCode, Account.CHANNEL_TYPE_D1);

            if (d1Merch != null) {
                switch (d1Merch.getStatus()) {
                    case MerchantChannelStatus.AUDIT_STATUS_EXAMINING:
                        throw new MsgException("进件审核中");
                    case MerchantChannelStatus.AUDIT_STATUS_SUCCESS:
                        // d1已进件通过, 此时说明需求进件的是银盛
                        MerchantBaseInfo mbi = mbiService.getMerchantBaseInfoByMerchantCode(merchantCode);

                        int ysCount = accountMapper.selectYSAuditSmallCount(mbi.getUserId());
                        if (ysCount >= 2) {
                            throw new MsgException("非营业执照商户同一结算人仅可申请两次实时到账");
                        }
                        break;
                    default:
                        break;
                }
            }
        }


        mcs.setStatus(MerchantChannelStatus.AUDIT_STATUS_EXAMINING);
        mcs.setThirdStatus(MerchantChannelStatus.AUDIT_THIRD_STATUS_WAITING);

        String remark = mcs.getRemark();
        if (StringUtils.isBlank(remark)) {
            mcs.setRemark("待后台审核");
        }

        saveOrUpdate(mcs);

        UserApp userApp = new UserApp().setMerchantCode(merchantCode).setUserType("promoter");
        userApp = userAppService.queryUserApp(userApp);

        wxTalkService.sendAuditAlert(userApp.getUserId() + "");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rejectAudit(String merchantCode, String errMsg) {
        MsgException.checkBlank(errMsg, "请补充驳回原因");

        List<Integer> validChannelIdList = merchantChannelService.getValidChannelIdList();
        LambdaQueryWrapper<MerchantChannelStatus> qWrapper = new LambdaQueryWrapper<MerchantChannelStatus>()
                .eq(MerchantChannelStatus::getMerchantCode, merchantCode)
                .and(wrapper -> wrapper.in(MerchantChannelStatus::getChannel, validChannelIdList)
                        .or()
                        .isNull(MerchantChannelStatus::getChannel))
                .eq(MerchantChannelStatus::getStatus, "1")
                .eq(MerchantChannelStatus::getThirdStatus, "-100");

        MerchantChannelStatus merchantChannelStatus = getOne(qWrapper);

        MerchantChannelStatus.checkCanAudit(merchantChannelStatus);

        // 添加行数据锁
        merchantChannelStatus = baseMapper.getByIdLock(merchantChannelStatus.getId());

        //
        merchantChannelStatus.setStatus(MerchantChannelStatus.AUDIT_STATUS_RESET);
        merchantChannelStatus.setRemark(errMsg);
        merchantChannelStatus.setCallbackStatus("1");
        merchantChannelStatus.setUpdateTime(new Date());
        updateById(merchantChannelStatus);

        UserApp userApp = new UserApp().setMerchantCode(merchantCode).setUserType("promoter");
        userApp = userAppService.queryUserApp(userApp);

        Notice notice = new Notice(1, 1, userApp);
        notice.setNoticeCode(System.currentTimeMillis() + "");
        notice.setUniqueKey(System.currentTimeMillis() + "");
        notice.setCreateDt(new Date());
        notice.setConrtent("商户进件驳回, " + errMsg);
        noticeService.saveNotice(notice);

        generalPushUtil.sendAllPlatByAlias(Collections.singletonList(userApp.getUserId() + ""), "收银呗审核通知", errMsg, "1");

        // 机器人发送已处理的信息到群组
        wxTalkService.sendAuditResultAlert(userApp.getUserId() + "");
    }

    @Override
    public ChannelStatusVO appQuickCash() {
        UserApp userApp = userAppService.queryUserAppByToken();

        MerchantChannelStatus one = getByMerchantCode(userApp.getMerchantCode(), 4);
        if (one != null && one.getStatus().equals(MerchantChannelStatus.AUDIT_STATUS_WAITING_SIGN)) {
            try {
                Map<String, Object> map = new HashMap<>();
                map.put("sysFlowId", one.getApplicationId());
                ysAuditServiceV2.merchantAuditResult(map);
                one = getByMerchantCode(userApp.getMerchantCode(), 4);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        ChannelStatusVO result = Converter.INSTANCE.toVO(one);
        if (result == null) {
            result = new ChannelStatusVO();
            result.setChannel(4);
            result.setHasQuickCash(true);
            result.setStatus(MerchantChannelStatus.AUDIT_STATUS_RESET);
        } else {
            result.setHasQuickCash(true);
        }

        /*
         * 操作
         */
        if (MerchantChannelStatus.AUDIT_STATUS_QUICK_CASH.equals(result.getStatus())) {
            result.setStatus(MerchantChannelStatus.AUDIT_STATUS_EXAMINING);
        }

        return result;
    }

    @Override
    public ChannelStatusVO appSwitchChannel(int flag) {
        UserApp userApp = userAppService.queryUserAppByToken();

        // 将所有通道的优先级设为0
        LambdaUpdateWrapper<MerchantChannelStatus> uWrapper = Wrappers.lambdaUpdate();
        uWrapper.eq(MerchantChannelStatus::getMerchantCode, userApp.getMerchantCode())
                .ne(MerchantChannelStatus::getValid, MerchantChannelStatus.VALID_STATUS_BAN)
                .set(MerchantChannelStatus::getValid, 0);
        update(uWrapper);

        LambdaQueryWrapper<MerchantChannelStatus> qWrapper = Wrappers.lambdaQuery();

        if (flag == 1) {
            qWrapper.eq(MerchantChannelStatus::getVirChannelFlag, Account.CHANNEL_TYPE_D0)
                    .eq(MerchantChannelStatus::getMerchantCode, userApp.getMerchantCode());

            MerchantChannelStatus quickChannel = getOne(qWrapper);

            MsgException.checkNull(quickChannel, "暂未开通快速通道");

            MsgException.checkEquals(quickChannel.getValid(), MerchantChannelStatus.VALID_STATUS_BAN, quickChannel.getRemark());

            if (!MerchantChannelStatus.isAudited(quickChannel)) {
                throw new MsgException("当前状态暂不允许切换通道");
            }

            quickChannel.setValid(1);
            updateById(quickChannel);

            LambdaQueryWrapper<SubMerchantApplyOrder> qWrapper2 = Wrappers.lambdaQuery();
            qWrapper2.eq(SubMerchantApplyOrder::getMerchantCode, quickChannel.getMerchantCode())
                    .eq(SubMerchantApplyOrder::getChannelId, quickChannel.getChannel())
                    .orderByDesc(SubMerchantApplyOrder::getId)
                    .last("limit 1");
            SubMerchantApplyOrder smao = smaoService.getOne(qWrapper2);
            if (smao == null || !SubMerchantApplyOrder.RES_STATUS_COMPLETE.equals(smao.getResultStatus())) {
                LambdaUpdateWrapper<MerchantBaseInfo> uWrapper2 = Wrappers.lambdaUpdate();
                uWrapper2.eq(MerchantBaseInfo::getUserId, userApp.getUserId())
                        .set(MerchantBaseInfo::getWxCertStatus, "0");
                mbiService.update(uWrapper2);
            }

            return Converter.INSTANCE.toVO(quickChannel);

        } else {
            qWrapper.eq(MerchantChannelStatus::getVirChannelFlag, Account.CHANNEL_TYPE_D1)
                    .eq(MerchantChannelStatus::getMerchantCode, userApp.getMerchantCode());

            MerchantChannelStatus channelStatus = getOne(qWrapper);

            MsgException.checkNull(channelStatus, "暂未进件");

            String status = channelStatus.getStatus();

            MsgException.checkEquals(channelStatus.getValid(), MerchantChannelStatus.VALID_STATUS_BAN, channelStatus.getRemark());

            if (!MerchantChannelStatus.AUDIT_STATUS_SUCCESS.equals(status) && !MerchantChannelStatus.AUDIT_STATUS_DATA_EDIT.equals(status)) {
                throw new MsgException("进件暂未通过");
            }

            channelStatus.setValid(1);
            updateById(channelStatus);

            LambdaQueryWrapper<SubMerchantApplyOrder> qWrapper2 = Wrappers.lambdaQuery();
            qWrapper2.eq(SubMerchantApplyOrder::getMerchantCode, channelStatus.getMerchantCode())
                    .eq(SubMerchantApplyOrder::getChannelId, channelStatus.getChannel())
                    .orderByDesc(SubMerchantApplyOrder::getStatus)
                    .orderByDesc(SubMerchantApplyOrder::getUpdateTime)
                    .last("limit 1");
            SubMerchantApplyOrder smao = smaoService.getOne(qWrapper2);
            if (smao == null || !SubMerchantApplyOrder.RES_STATUS_COMPLETE.equals(smao.getResultStatus())) {
                LambdaUpdateWrapper<MerchantBaseInfo> uWrapper2 = Wrappers.lambdaUpdate();
                uWrapper2.eq(MerchantBaseInfo::getUserId, userApp.getUserId())
                        .set(MerchantBaseInfo::getWxCertStatus, "0");
                mbiService.update(uWrapper2);
            }

            return Converter.INSTANCE.toVO(channelStatus);
        }
    }

    @Override
    public ChannelStatusVO appCurrent() {
        UserApp userApp = userAppService.queryUserAppByToken();
        MerchantChannelStatus entity = getValidData(userApp.getMerchantCode());

        ChannelStatusVO channelStatusVO = Converter.INSTANCE.toVO(entity);

        if (channelStatusVO == null) {
            channelStatusVO = new ChannelStatusVO();
            channelStatusVO.setStatus(MerchantChannelStatus.AUDIT_STATUS_REJECT);
            channelStatusVO.setHasQuickCash(false);
        } else {
            channelStatusVO.setHasQuickCash(Objects.equals(channelStatusVO.getChannel(), 4));
        }

        return channelStatusVO;
    }


    @Override
    public MerchantChannelStatus getChannelByMerchantId(String merchantId) {
        QueryWrapper<MerchantChannelStatus> queryWrapper = new QueryWrapper<MerchantChannelStatus>().eq("merchantId",merchantId);
        return this.baseMapper.selectOne(queryWrapper);
    }

    @Override
//    @Async
    public void verifyWxAuthStatus(MerchantChannelStatus mcs) {
        if (mcs == null) {
            return;
        }

        if (!MerchantChannelStatus.isAudited(mcs)) {
            return;
        }

        if (mcs.getChannel() == null) {
            return;
        }

        if (StringUtils.isBlank(mcs.getMerchantId())) {
            return;
        }

        if (Objects.equals(mcs.getAuthorizationStatus(), MerchantChannelStatus.AUTHORIZATION_STATUS_AUTHORIZED)) {
            return;
        }

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

    @Override
    public MerchantChannelStatus getByMerchantId(String mno) {
        QueryWrapper<MerchantChannelStatus> queryWrapper = new QueryWrapper<MerchantChannelStatus>().eq("merchantId", mno);
        return baseMapper.selectOne(queryWrapper);
    }

    @Override
    public void sendSignMsg(String merchantCode) {
        MerchantChannelStatus mcs = getByMerchantCode(merchantCode, 4);
        if (mcs == null) {
            throw new MsgException("商户信息不存在");
        }

        if (!MerchantChannelStatus.AUDIT_STATUS_WAITING_SIGN.equals(mcs.getStatus())) {
            throw new MsgException("非待签约商户禁止该请求");
        }

        ysMerchProtocolService.sendProtocolMsg(mcs);
    }

    /**
     * 当前用户指定时间段 进件商户数量
     */
    @Override
    public UserNumVO getUserNumInfo(Long userId, String date, Integer dateType) {
        return baseMapper.getUserNumInfo(userId,date,dateType);
    }
}
