package com.yeejoin.amos.boot.module.jyjc.biz.event.rule.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.entity.BaseEntity;
import com.yeejoin.amos.boot.biz.common.utils.RedisKey;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.boot.biz.common.utils.SnowflakeIdUtil;
import com.yeejoin.amos.boot.module.jyjc.api.entity.JyjcInspectionApplicationNoAcceptLog;
import com.yeejoin.amos.boot.module.jyjc.api.enums.JYJCTypeEnum;
import com.yeejoin.amos.boot.module.jyjc.api.enums.RequestTypeEnum;
import com.yeejoin.amos.boot.module.jyjc.api.mapper.JyjcInspectionApplicationNoAcceptLogMapper;
import com.yeejoin.amos.boot.module.jyjc.api.model.InspectionEquipInfoModel;
import com.yeejoin.amos.boot.module.jyjc.biz.event.InspectionOrgRefreshEvent;
import com.yeejoin.amos.boot.module.jyjc.biz.event.TouchRuleEvent;
import com.yeejoin.amos.boot.module.jyjc.biz.event.listener.InspectionApplicationPushEventListener;
import com.yeejoin.amos.boot.module.jyjc.biz.event.publisher.EventPublisher;
import com.yeejoin.amos.boot.module.jyjc.biz.rule.InspectionEquipInfo;
import com.yeejoin.amos.boot.module.jyjc.biz.service.impl.RuleCommonServiceImpl;
import com.yeejoin.amos.boot.module.ymt.api.entity.IdxBizJgProjectContraption;
import com.yeejoin.amos.boot.module.ymt.api.entity.RegistrationInfo;
import com.yeejoin.amos.boot.module.ymt.api.entity.TzBaseEnterpriseInfo;
import com.yeejoin.amos.boot.module.ymt.api.mapper.IdxBizJgProjectContraptionMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.RegistrationInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.mapper.TzBaseEnterpriseInfoMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

import static com.yeejoin.amos.boot.module.jyjc.api.enums.CategoryEnum.getCategoryByType;

/**
 * 启用规则时业务处理
 *
 * @author Administrator
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class EnableRuleDataPreparationService {

    private final SnowflakeIdUtil sequence;

    private final RegistrationInfoMapper registrationInfoMapper;

    private final RuleCommonServiceImpl ruleCommonService;

    private final InspectionApplicationPushEventListener applicationPushEventListener;

    private final JyjcInspectionApplicationNoAcceptLogMapper inspectionApplicationNoAcceptLogMapper;

    private final EventPublisher publisher;

    private final List<BlockingQueue<InspectionEquipInfoModel>> hashCodeBlockingQueues = new ArrayList<>();

    private final IdxBizJgProjectContraptionMapper jgProjectContraptionMapper;

    private final TzBaseEnterpriseInfoMapper baseEnterpriseInfoMapper;

    private final RedisUtils redisUtils;

    @Value("${rule.data.preparation.thread.number:2}")
    private int threadNumber;

    /**
     * 默认的企业标签：管控等级
     */
    @Value("${enterprise.regulatoryLabels.default.value:三级管控}")
    private String defaultRegulatoryLabels;

    /**
     * 压力类设备种类
     */
    private static final List<String> PRESSURE_EQU_LIST = Arrays.asList("8000", "1000", "2000");

    /**
     * 需要技术参数匹配报检的设备类别-目的提高执行速度
     */
    private static final List<String> NEED_TECH_PARAM_EQU_CATEGORY = Collections.singletonList("1100");


    public void onApplicationEvent(InspectionOrgRefreshEvent event) {
        int queueIndex = Math.abs(event.getInspectionEquipInfoModel().getRecord().hashCode()) % threadNumber;
        hashCodeBlockingQueues.get(queueIndex).add(event.getInspectionEquipInfoModel());
    }

    @PostConstruct
    public void init() {
        // 1.初始化队列，按照线程数动态创建队列
        initQueue();
        // 2.初始化多线程消费线程
        ExecutorService executorService = Executors.newFixedThreadPool(threadNumber);
        for (int i = 0; i < threadNumber; i++) {
            BlockingQueue<InspectionEquipInfoModel> queue = hashCodeBlockingQueues.get(i);
            executorService.execute(() -> {
                while (true) {
                    try {
                        InspectionEquipInfoModel fillingRecordStatisticsUnitDayDto = queue.take();
                        this.dealData(fillingRecordStatisticsUnitDayDto);
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                    }
                }
            });
        }
    }

    private void initQueue() {
        for (int i = 0; i < threadNumber; i++) {
            hashCodeBlockingQueues.add(new LinkedBlockingQueue<>());
        }
    }

    private void dealData(InspectionEquipInfoModel equipInfoModel) {
        InspectionEquipInfo inspectionEquipInfo = new InspectionEquipInfo();
        if (equipInfoModel.getEquCategory() != null && equipInfoModel.getEquCategory().startsWith("8")) {
            // 管道逻辑
            String projectContraptionId = equipInfoModel.getRecord();
            IdxBizJgProjectContraption projectContraption = jgProjectContraptionMapper.selectById(projectContraptionId);
            if (projectContraption == null) {
                log.error("未找到装置，报检规则匹配流程结束！");
                return;
            }
            inspectionEquipInfo.setEquCategory(equipInfoModel.getEquCategory());
            inspectionEquipInfo.setEquList(equipInfoModel.getEquList());
            inspectionEquipInfo.setEquDefine(equipInfoModel.getEquDefine());
            inspectionEquipInfo.setTechParams(new HashMap<>());
        } else {
            // 非管道逻辑
            RegistrationInfo registrationInfo = fetchRegistrationInfo(equipInfoModel.getRecord());
            if (registrationInfo == null) {
                log.error("未找到设备，报检规则匹配流程结束！");
                return;
            }
            inspectionEquipInfo.setEquCategory(equipInfoModel.getEquCategory());
            inspectionEquipInfo.setEquList(equipInfoModel.getEquList());
            inspectionEquipInfo.setEquDefine(equipInfoModel.getEquDefine());
            inspectionEquipInfo.setTechParams(this.getTechParams(registrationInfo, equipInfoModel));
            // 是否球罐 0 1 转 boolean
            inspectionEquipInfo.setIsBallValve(!"0".equals(registrationInfo.getWhetherSphericalTank()));
        }
        if (PRESSURE_EQU_LIST.contains(equipInfoModel.getEquList())) {
            ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(equipInfoModel.getUserId(), equipInfoModel.getToken())).toString(), ReginParams.class);
            setCompanyInfo(reginParams, inspectionEquipInfo);
            TzBaseEnterpriseInfo enterpriseInfo = baseEnterpriseInfoMapper.selectOne(new LambdaQueryWrapper<TzBaseEnterpriseInfo>().eq(TzBaseEnterpriseInfo::getUseCode, reginParams.getCompany().getCompanyCode()).select(BaseEntity::getSequenceNbr, TzBaseEnterpriseInfo::getRegulatoryLabels));
            inspectionEquipInfo.setManageLevel(StringUtils.isNotBlank(enterpriseInfo.getRegulatoryLabels()) ? enterpriseInfo.getRegulatoryLabels() : defaultRegulatoryLabels);
        } else {
            ReginParams reginParams = JSON.parseObject(redisUtils.get(RedisKey.buildReginKey(equipInfoModel.getUserId(), equipInfoModel.getToken())).toString(), ReginParams.class);
            setCompanyInfo(reginParams, inspectionEquipInfo);
        }
        inspectionEquipInfo.setAreaCode(ruleCommonService.getArea(equipInfoModel.getCity(), equipInfoModel.getCounty()));
        inspectionEquipInfo.setDistrictOrCountyCode(equipInfoModel.getCounty());
        inspectionEquipInfo.setComponentKey(equipInfoModel.getComponentKey());
        inspectionEquipInfo.setInspectionType(equipInfoModel.getInspectionType());
        inspectionEquipInfo.setRecord(equipInfoModel.getRecord());
        inspectionEquipInfo.setBizType(getCategoryByType(JYJCTypeEnum.of(inspectionEquipInfo.getInspectionType())));
        inspectionEquipInfo.setUuid(sequence.nextId() + "");
        JyjcInspectionApplicationNoAcceptLog jyjcInspectionApplicationNoAcceptLog = getLastNoAcceptLog(equipInfoModel);
        inspectionEquipInfo.setRequestType(this.buildRequestType(equipInfoModel, jyjcInspectionApplicationNoAcceptLog));
        inspectionEquipInfo.setLastNoAcceptInspectionCode(this.buildLastNoAcceptInspectionCode(jyjcInspectionApplicationNoAcceptLog));
        inspectionEquipInfo.setAppSeq(equipInfoModel.getAppSeq());
        // 触发规则
        publisher.publish(new TouchRuleEvent(this, inspectionEquipInfo));
    }

    private static void setCompanyInfo(ReginParams reginParams, InspectionEquipInfo inspectionEquipInfo) {
        Map<String, Object> companyInfo = new HashMap<>();
        companyInfo.put("companyType", reginParams.getCompany().getCompanyType());
        companyInfo.put("companyCode", reginParams.getCompany().getCompanyCode());
        inspectionEquipInfo.setCompanyInfo(companyInfo);
    }

    private String buildLastNoAcceptInspectionCode(JyjcInspectionApplicationNoAcceptLog jyjcInspectionApplicationNoAcceptLog) {
        if (jyjcInspectionApplicationNoAcceptLog != null) {
            return jyjcInspectionApplicationNoAcceptLog.getInspectionUnitCode();
        }
        return "";
    }


    private Map<String, Object> getTechParams(RegistrationInfo registrationInfo, InspectionEquipInfoModel equipInfoModel) {
        if (NEED_TECH_PARAM_EQU_CATEGORY.contains(equipInfoModel.getEquCategory())) {
            return applicationPushEventListener.populateEquipInfoWithTechParams(registrationInfo.getEquList(), registrationInfo.getRecord());
        }
        return new HashMap<>();
    }

    private String buildRequestType(InspectionEquipInfoModel equipInfoModel, JyjcInspectionApplicationNoAcceptLog jyjcInspectionApplicationNoAcceptLog) {
        // 工作台发起申请
        if (StringUtils.isEmpty(equipInfoModel.getAppSeq())) {
            return RequestTypeEnum.FIRST_REQUEST.getCode();
        }
        // 没有不予受理请求记录
        if (jyjcInspectionApplicationNoAcceptLog == null) {
            return RequestTypeEnum.FIRST_REQUEST.getCode();
        }
        // 有记录
        return RequestTypeEnum.NO_ACCEPT_REQUEST.getCode();
    }

    private JyjcInspectionApplicationNoAcceptLog getLastNoAcceptLog(InspectionEquipInfoModel equipInfoModel) {
        LambdaQueryWrapper<JyjcInspectionApplicationNoAcceptLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(JyjcInspectionApplicationNoAcceptLog::getApplicationSeq, equipInfoModel.getAppSeq());
        wrapper.orderByDesc(JyjcInspectionApplicationNoAcceptLog::getRecDate);
        wrapper.last("limit 1");
        wrapper.select(JyjcInspectionApplicationNoAcceptLog::getApplicationSeq, JyjcInspectionApplicationNoAcceptLog::getInspectionUnitCode);
        return inspectionApplicationNoAcceptLogMapper.selectOne(wrapper);
    }

    private RegistrationInfo fetchRegistrationInfo(String record) {
        return registrationInfoMapper.selectOne(
                Wrappers.<RegistrationInfo>lambdaQuery().select(RegistrationInfo::getRecord, RegistrationInfo::getEquCategory,
                                RegistrationInfo::getEquDefine, RegistrationInfo::getEquList, RegistrationInfo::getWhetherSphericalTank)
                        .eq(RegistrationInfo::getRecord, record));
    }
}

