package com.jeequan.jeepay.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.core.constants.ApiCodeEnum;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.utils.RegKit;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.service.mapper.MchQrcodeCardMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 商户码牌表 服务实现类
 * </p>
 *
 * @author [mybatis plus generator]
 * @since 2021-12-28
 */
@Service
public class MchQrcodeCardService extends ServiceImpl<MchQrcodeCardMapper, MchQrcodeCard> {

    @Autowired private MchAppService mchAppService;
    @Autowired private MchStoreService mchStoreService;
    @Autowired private MchStoreDeviceService mchStoreDeviceService;
    @Autowired private MchQrcDeviceRelaService mchQrcDeviceRelaService;
    @Autowired private AgentInfoService agentInfoService;
    @Autowired private MchApplymentService mchApplymentService;
    @Autowired private MchInfoService mchInfoService;
    @Autowired private MchQrcodeCardMapper mchQrcodeCardMapper;

    /** 查询分页记录 **/
    public IPage<MchQrcodeCard> selectPageRecords(IPage page, MchQrcodeCard condition){
        // 获取查询时间请求参数  [开始时间,  结束时间]
        Date[] queryDateRangeArray = condition.buildQueryDateRange();
        if(queryDateRangeArray[0] != null){
            condition.setFirstDate(queryDateRangeArray[0]);
        }
        if(queryDateRangeArray[1] != null){
            condition.setLastDate(queryDateRangeArray[1]);
        }

        IPage<MchQrcodeCard> mchQrcodeCardIPage = mchQrcodeCardMapper.selectPageRecords(page, condition);
        for (MchQrcodeCard record : mchQrcodeCardIPage.getRecords()) {
            //手机号脱敏
            if (StringUtils.isNotEmpty(record.getMchServicePhone())){
                record.setMchServicePhone(DesensitizedUtil.mobilePhone(record.getMchServicePhone()));
            }
            if (StringUtils.isNotEmpty(record.getMchUserPhone())){
                record.setMchUserPhone(DesensitizedUtil.mobilePhone(record.getMchUserPhone()));
            }
        }

        return mchQrcodeCardIPage;
    }

    public boolean addQrCode(MchQrcodeCard mchQrCode, Byte belongType) {

        if (StringUtils.isNotEmpty(mchQrCode.getMchNo())) {
            MchStore mchStore = mchStoreService.queryDefaultStore(mchQrCode.getMchNo());
            if(mchStore == null){
                throw new BizException("门店不存在！");
            }
            mchQrCode.setStoreId(mchStore.getStoreId());
            // 默认已绑定
            mchQrCode.setBindState(CS.YES);
        }
        mchQrCode.setQrcBelongType(belongType);
        return save(mchQrCode);
    }

    public IPage<MchQrcodeCard> listByPage(IPage iPage, MchQrcodeCard mchQrcodeCard, LambdaQueryWrapper<MchQrcodeCard> wrapper) {

        wrapper.eq(StringUtils.isNotEmpty(mchQrcodeCard.getMchNo()), MchQrcodeCard::getMchNo, mchQrcodeCard.getMchNo());
        wrapper.eq(StringUtils.isNotEmpty(mchQrcodeCard.getBatchId()), MchQrcodeCard::getBatchId, mchQrcodeCard.getBatchId());

        // 时间范围条件
        Date[] dateRange = mchQrcodeCard.buildQueryDateRange();
        if (dateRange[0] != null) {
            wrapper.ge(MchQrcodeCard::getCreatedAt, dateRange[0]);
        }
        if (dateRange[1] != null) {
            wrapper.le(MchQrcodeCard::getCreatedAt, dateRange[1]);
        }

        //根据ID查询
        if(StringUtils.isNotEmpty(mchQrcodeCard.extv().getString("idsStr"))){

            List<String> ids = Arrays.asList(mchQrcodeCard.extv().getString("idsStr").split("_"));
            if(ids.size() > 0 ){
                wrapper.in(MchQrcodeCard::getQrcId, ids);
            }
        }

        wrapper.orderByDesc(MchQrcodeCard::getCreatedAt);

        return page(iPage, wrapper);
    }


    public long countByWrapper(MchQrcodeCard mchQrcodeCard) {

        LambdaQueryWrapper<MchQrcodeCard> wrapper = MchQrcodeCard.gw();
        wrapper.eq(StringUtils.isNotEmpty(mchQrcodeCard.getMchNo()), MchQrcodeCard::getMchNo, mchQrcodeCard.getMchNo());
        wrapper.eq(StringUtils.isNotEmpty(mchQrcodeCard.getBatchId()), MchQrcodeCard::getBatchId, mchQrcodeCard.getBatchId());

        // 时间范围条件
        Date[] dateRange = mchQrcodeCard.buildQueryDateRange();
        if (dateRange[0] != null) {
            wrapper.ge(MchQrcodeCard::getCreatedAt, dateRange[0]);
        }
        if (dateRange[1] != null) {
            wrapper.le(MchQrcodeCard::getCreatedAt, dateRange[1]);
        }


        //根据ID查询
        if(StringUtils.isNotEmpty(mchQrcodeCard.extv().getString("idsStr"))){

            List<String> ids = Arrays.asList(mchQrcodeCard.extv().getString("idsStr").split("_"));
            if(ids.size() > 0 ){
                wrapper.in(MchQrcodeCard::getQrcId, ids);
            }
        }

        return count(wrapper);
    }

    /** 修改或重新绑定码牌 */
    public void updateOrReBindQR(MchQrcodeCard updateRecord, MchQrcodeCard dbRecord) {
        // 1、更新码牌
        //自动处理商户信息
        if (StringUtils.isNotEmpty(updateRecord.getStoreId())){
            MchStore mchStore = mchStoreService.getById(updateRecord.getStoreId());
            if (StringUtils.isNotEmpty(mchStore.getMchApplyId())){
                MchApplyment applyment = mchApplymentService.getById(mchStore.getMchApplyId());
                if (applyment != null){
                    updateRecord.setMchApplyName(applyment.getMchShortName());
                    updateRecord.setMchApplyId(mchStore.getMchApplyId());
                }
            }
        }
        boolean result = updateById(updateRecord);
        if (!result) {
            throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
        }

        // 2、更新绑定信息
        if (updateRecord.getBindState() == null || updateRecord.getBindState() == CS.NO
                || updateRecord.getStoreId() == null || StringUtils.isBlank(updateRecord.getAppId())) {
            return;
        }
        if (!updateRecord.getStoreId().equals(dbRecord.getStoreId()) || !updateRecord.getAppId().equals(dbRecord.getAppId())) {
            bindEmptyQR(updateRecord);
        }
    }

    /**
     * 划拨码牌
     */
    @Transactional
    public boolean allotQrc(Boolean isAllotDeviceSync, String agentNo, List<Long> qrcIdList, List<String> mchNoList, List<String> subAgentNoList) {

        // 再次筛选未绑定的码，已绑定的码不可再次划拨
        List<MchQrcodeCard> bindList = this.list(MchQrcodeCard.gw()
                .in(MchQrcodeCard::getQrcId, qrcIdList)
                .eq(MchQrcodeCard::getBindState, CS.YES)
        );

        // 选择的码牌存在已绑定的
        if (CollUtil.isNotEmpty(bindList)) {

            if (CollUtil.isEmpty(mchNoList)) {
                throw new BizException("码牌已绑定商户，且绑定的商户不属于要划拨的服务商，请重新选择");
            }

            for (MchQrcodeCard mchQrcodeCard : bindList) {
                if (!mchNoList.contains(mchQrcodeCard.getMchNo())) {
                    throw new BizException("码牌【" + mchQrcodeCard.getQrcId() + "】已绑定商户，且绑定的商户不属于要划拨的服务商，请重新选择");
                }
            }
        }

        boolean result;

        // 1、同步划拨绑定的设备
        if (isAllotDeviceSync) {

            // 要同步划拨的  云喇叭设备集合
            List<MchStoreDevice> deviceList = mchStoreDeviceService.list(MchStoreDevice.gw().in(MchStoreDevice::getBindQrcId, qrcIdList));

            if (!CollectionUtils.isEmpty(deviceList)) {
                // 要同步划拨的设备ID集合
                List<Long> deviceIdList = deviceList.stream().map(MchStoreDevice::getDeviceId).collect(Collectors.toList());

                result = mchStoreDeviceService.allotDevice(false, agentNo, deviceIdList, mchNoList, subAgentNoList);
                if (!result) {
                    throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
                }
            }
        }


        // 2、划拨码牌
        result = this.update(new LambdaUpdateWrapper<MchQrcodeCard>()
                .set(MchQrcodeCard::getAgentNo, agentNo)
                .in(MchQrcodeCard::getQrcId, qrcIdList)
                .and(i ->{
                    i.in(CollUtil.isNotEmpty(subAgentNoList), MchQrcodeCard::getAgentNo, subAgentNoList)
                            .or().isNull(MchQrcodeCard::getAgentNo)
                            .or().eq(MchQrcodeCard::getAgentNo, "");
                })
        );
        if (!result) {
            throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
        }

        return true;
    }

    /**
     * 收回码牌
     */
    @Transactional
    public boolean recoverQrc(Boolean isRecoverDeviceSync, List<Long> qrcIdList, List<String> subAgentNoList, String recoverAgentNo) {

        boolean result;

        // 1、同步收回绑定的设备
        if (isRecoverDeviceSync) {

            // 要同步收回的  云喇叭设备集合
            List<MchStoreDevice> deviceList = mchStoreDeviceService.list(MchStoreDevice.gw().in(MchStoreDevice::getBindQrcId, qrcIdList));

            if (!CollectionUtils.isEmpty(deviceList)) {
                // 要同步收回的设备ID集合
                List<Long> deviceIdList = deviceList.stream().map(MchStoreDevice::getDeviceId).collect(Collectors.toList());

                result = mchStoreDeviceService.recoverDevice(false, deviceIdList, subAgentNoList, recoverAgentNo);
                if (!result) {
                    throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
                }
            }
        }

        // 2、收回码牌
        result = this.update(new LambdaUpdateWrapper<MchQrcodeCard>()
                .set(MchQrcodeCard::getAgentNo, StringUtils.isBlank(recoverAgentNo) ? "" : recoverAgentNo)
                .in(MchQrcodeCard::getQrcId, qrcIdList)
                .in(CollUtil.isNotEmpty(subAgentNoList), MchQrcodeCard::getAgentNo, subAgentNoList)
        );
        if (!result) {
            throw new BizException(ApiCodeEnum.SYS_OPERATION_FAIL_UPDATE);
        }

        return true;
    }

    /**
     * 绑定码牌
     */
    @Transactional
    public void bindEmptyQR(MchQrcodeCard record) {

        // 1、绑定码牌
        boolean result = this.updateById(record);
        if (!result) {
            throw new BizException("绑定失败！");
        }

        // 2、绑定云喇叭 && 更新码牌、设备关联关系
        MchStoreDevice mchStoreDevice = mchStoreDeviceService.getByBindQrcId(record.getQrcId());
        if (mchStoreDevice == null) {
            return;
        }

        MchStoreDevice updateRecord = new MchStoreDevice();
        updateRecord.setDeviceId(mchStoreDevice.getDeviceId());
        updateRecord.setMchNo(record.getMchNo());
        updateRecord.setStoreId(record.getStoreId());
        updateRecord.setBindState(CS.YES);
        if (StringUtils.isNotEmpty(record.getMchApplyName())){
            updateRecord.setMchApplyName(record.getMchApplyName());
            updateRecord.setMchApplyId(record.getMchApplyId());
        }
        if (StringUtils.isNotBlank(record.getAgentNo())) {
            updateRecord.setAgentNo(record.getAgentNo());
        }

        result = mchStoreDeviceService.updateById(updateRecord);
        if (!result) {
            throw new BizException("绑定失败");
        }

        mchQrcDeviceRelaService.removeByQrcId(record.getQrcId());

        MchQrcDeviceRela mchQrcDeviceRela = new MchQrcDeviceRela();
        mchQrcDeviceRela.setQrcId(record.getQrcId()).setDeviceId(mchStoreDevice.getDeviceId());
        result = mchQrcDeviceRelaService.save(mchQrcDeviceRela);
        if (!result) {
            throw new BizException("绑定失败");
        }
    }

    /**
     * 绑定码牌【根据ID、商户号、门店ID、应用ID】
     */
    public boolean bindByIds(List<Long> qrcIdList, String mchNo, String storeId, String appId, String agentNo) {

        // appId空，则使用默认商户app
        if (StringUtils.isBlank(appId)) {
            appId = mchAppService.getDefaultApp(mchNo).getAppId();
        }

        LambdaUpdateWrapper<MchQrcodeCard> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(MchQrcodeCard::getMchNo, mchNo)
                .set(storeId != null, MchQrcodeCard::getStoreId, storeId)
                .set(MchQrcodeCard::getAppId, appId)
                .set(MchQrcodeCard::getBindState, CS.YES)
                .set(StringUtils.isNotBlank(agentNo), MchQrcodeCard::getAgentNo, agentNo)
                .in(MchQrcodeCard::getQrcId, qrcIdList);

        return this.update(updateWrapper);
    }

    /**
     * 解绑码牌
     */
    @Transactional
    public void unbind(MchQrcodeCard dbRecord) {

        // 解绑码牌
        boolean result = unbindByIds(Collections.singletonList(dbRecord.getQrcId()));
        if(!result) {
            throw new BizException("解绑失败");
        }

        // 解绑初始绑定的云喇叭设备
        MchStoreDevice mchStoreDevice = mchStoreDeviceService.getByBindQrcId(dbRecord.getQrcId());
        if (mchStoreDevice == null) {
            return;
        }

        result = mchStoreDeviceService.unbindByIds(Collections.singletonList(mchStoreDevice.getDeviceId()));
        if(!result) {
            throw new BizException("解绑失败");
        }

        // 删除全部相关关联关系
        result = mchQrcDeviceRelaService.removeByQrcId(dbRecord.getQrcId());
        if(!result) {
            throw new BizException("解绑失败");
        }
    }

    /**
     * 解绑码牌【根据ID】
     */
    public boolean unbindByIds(List<Long> qrcIdList) {

        LambdaUpdateWrapper<MchQrcodeCard> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(MchQrcodeCard::getMchNo, "")
                .set(MchQrcodeCard::getStoreId, 0L)
                .set(MchQrcodeCard::getAppId, "")
                .set(MchQrcodeCard::getBindState, CS.NO)
                .in(MchQrcodeCard::getQrcId, qrcIdList);

        return this.update(updateWrapper);
    }

    public IPage<MchStoreDevice> getBindDevice(IPage iPage, MchQrcodeCard dbRecord, String agentNo) {

        List<Long> deviceIdList = new LinkedList<>();

        List<MchQrcDeviceRela> relaList = mchQrcDeviceRelaService.list(MchQrcDeviceRela.gw().eq(MchQrcDeviceRela::getQrcId, dbRecord.getQrcId()));
        if (!CollectionUtils.isEmpty(relaList)) {
            deviceIdList = relaList.stream().map(MchQrcDeviceRela::getDeviceId).collect(Collectors.toList());
        }

        List<Long> finalDeviceIdList = deviceIdList;
        return mchStoreDeviceService.page(iPage, MchStoreDevice.gw()
                .eq(StringUtils.isNotBlank(agentNo), MchStoreDevice::getAgentNo, agentNo)
                .eq(MchStoreDevice::getDeviceType, MchStoreDevice.DEVICE_TYPE_SPEAKER)
                .eq(MchStoreDevice::getBindState, CS.YES)
                .eq(MchStoreDevice::getState, CS.YES)
                .eq(MchStoreDevice::getStoreId, dbRecord.getStoreId())
                .and(i -> i.eq(MchStoreDevice::getBindType, MchStoreDevice.DEVICE_BIND_TYPE_STORE)
                        .or().in(!CollectionUtils.isEmpty(finalDeviceIdList), MchStoreDevice::getDeviceId, finalDeviceIdList)
                )
        );
    }

    /**
     * 查询码牌是否支持绑定
     * @param qrcId
     */
    public void checkQrCodeBind(String qrcId) {
        MchQrcodeCard mchQrcodeCard = baseMapper.selectById(qrcId);
        if(mchQrcodeCard == null){
            throw new BizException("当前码牌已被删除，无法使用，请更换新的码牌");
        }
        if(CS.YES == mchQrcodeCard.getBindState() || CS.NO == mchQrcodeCard.getQrcState()){
            throw new BizException("当前码牌已被停用或已被其他门店绑定");
        }
        if(MchQrcodeCard.QRC_TYPE_DZ == mchQrcodeCard.getQrcType()){
            throw new BizException("当前码牌为电子码牌，不支持绑定");
        }
    }
}
