package com.yeejoin.amos.boot.module.jyjc.biz.listener;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yeejoin.amos.boot.module.jyjc.api.enums.EquipCategoryEnum;
import com.yeejoin.amos.boot.module.jyjc.api.enums.JYJCTypeEnum;
import com.yeejoin.amos.boot.module.jyjc.api.enums.TopicEnum;
import com.yeejoin.amos.boot.module.jyjc.api.model.InspectionEquipInfoModel;
import com.yeejoin.amos.boot.module.jyjc.biz.listener.message.BizMessage;
import com.yeejoin.amos.boot.module.jyjc.biz.rule.InspectionEquipInfo;
import com.yeejoin.amos.boot.module.ymt.api.entity.*;
import com.yeejoin.amos.boot.module.ymt.api.mapper.*;
import com.yeejoin.amos.component.robot.AmosRequestContext;
import com.yeejoin.amos.component.rule.RuleTrigger;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.typroject.tyboot.component.emq.EmqKeeper;
import org.typroject.tyboot.component.emq.EmqxListener;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import static com.alibaba.fastjson.JSON.parseObject;
import static com.alibaba.fastjson.JSON.toJSONString;
import static com.yeejoin.amos.boot.module.jyjc.api.enums.CategoryEnum.getCategoryByType;

/**
 * @author Administrator
 */
@Component
@Slf4j
public class InspectionOrgRefreshListener extends EmqxListener {
    private static final BlockingQueue<BizMessage> BLOCKING_QUEUE = new LinkedBlockingQueue<>();

    @Value("${inspection.rule.project-name:报检规则}")
    private String ruleName;
    @Autowired
    private EmqKeeper emqKeeper;
    @Autowired
    private RuleTrigger ruleTrigger;
    @Autowired
    private AmosRequestContext amosRequestContext;
    @Autowired
    private RegistrationInfoMapper registrationInfoMapper;
    @Autowired
    private EquipTechParamBoilerMapper equipTechParamBoilerMapper;
    @Autowired
    private EquipTechParamVesselMapper equipTechParamVesselMapper;
    @Autowired
    private EquipTechParamElevatorMapper equipTechParamElevatorMapper;
    @Autowired
    private EquipTechParamLiftingMapper equipTechParamLiftingMapper;
    @Autowired
    private EquipTechParamVehicleMapper equipTechParamVehicleMapper;
    @Autowired
    private EquipTechParamRidesMapper equipTechParamRidesMapper;
    @Autowired
    private EquipTechParamPipelineMapper equipTechParamPipelineMapper;
    @Autowired
    private EquipTechParamRopewayMapper equipTechParamRopewayMapper;

    @Override
    public void processMessage(String topic, MqttMessage message) {
        if (log.isInfoEnabled()) {
            log.info("收到消息主题：{},消息内容：{}", topic, message.toString());
        }
        BLOCKING_QUEUE.add(new BizMessage(topic, message));
    }

    @PostConstruct
    public void init() throws Exception {
        emqKeeper.subscript(TopicEnum.INSPECTION_LIST_REFRESH.getTopic(), 2, this);
        Executors.newSingleThreadExecutor().submit(this::processMessages);
    }

    private void processMessages() {
        while (true) {
            try {
                BizMessage bizMessage = BLOCKING_QUEUE.take();
                processBizMessage(bizMessage);
            } catch (Exception e) {
                log.error("数据处理失败", e);
            }
        }
    }

    private void processBizMessage(BizMessage bizMessage) {
        byte[] payload = bizMessage.getMessage().getPayload();

        InspectionEquipInfoModel equipInfoModel = parseObject(new String(payload, StandardCharsets.UTF_8), InspectionEquipInfoModel.class);
        RegistrationInfo registrationInfo = fetchRegistrationInfo(equipInfoModel.getRecord());
        InspectionEquipInfo inspectionEquipInfo = new InspectionEquipInfo();
        if (registrationInfo != null) {
            inspectionEquipInfo.setEquCategory(registrationInfo.getEquCategory());
            inspectionEquipInfo.setEquList(registrationInfo.getEquList());
            inspectionEquipInfo.setEquDefine(registrationInfo.getEquDefine());
            inspectionEquipInfo.setComponentKey(bizMessage.getTopic().split("/")[0]);
            inspectionEquipInfo.setInspectionType(equipInfoModel.getInspectionType());
            inspectionEquipInfo.setRecord(equipInfoModel.getRecord());
            populateEquipInfoWithTechParams(inspectionEquipInfo, registrationInfo);
        }

        inspectionEquipInfo.setBizType(getCategoryByType(JYJCTypeEnum.of(inspectionEquipInfo.getInspectionType())));
        touchRule(inspectionEquipInfo);
    }

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

    private void populateEquipInfoWithTechParams(InspectionEquipInfo inspectionEquipInfo, RegistrationInfo registrationInfo) {
        EquipCategoryEnum productType = EquipCategoryEnum.of(Integer.parseInt(registrationInfo.getEquList()));
        switch (Objects.requireNonNull(productType)) {
            case IDX_BIZ_JG_TECH_PARAMS_BOILER:
                inspectionEquipInfo.setTechParams(BeanUtil.beanToMap(equipTechParamBoilerMapper.getBoilerByDefaultValue(registrationInfo.getRecord())));
                break;
            case IDX_BIZ_JG_TECH_PARAMS_VESSEL:
                inspectionEquipInfo.setTechParams(BeanUtil.beanToMap(equipTechParamVesselMapper.getVesselByDefaultValue(registrationInfo.getRecord())));
                break;
            case IDX_BIZ_JG_TECH_PARAMS_ELEVATOR:
                inspectionEquipInfo.setTechParams(BeanUtil.beanToMap(equipTechParamElevatorMapper.getElevatorByDefaultValue(registrationInfo.getRecord())));
                break;
            case IDX_BIZ_JG_TECH_PARAMS_LIFTING:
                inspectionEquipInfo.setTechParams(BeanUtil.beanToMap(equipTechParamLiftingMapper.getLiftingByDefaultValue(registrationInfo.getRecord())));
                break;
            case IDX_BIZ_JG_TECH_PARAMS_VEHICLE:
                inspectionEquipInfo.setTechParams(BeanUtil.beanToMap(equipTechParamVehicleMapper.getVehicleByDefaultValue(registrationInfo.getRecord())));
                break;
            case IDX_BIZ_JG_TECH_PARAMS_RIDES:
                inspectionEquipInfo.setTechParams(BeanUtil.beanToMap(equipTechParamRidesMapper.getRidesByDefaultValue(registrationInfo.getRecord())));
                break;
            case IDX_BIZ_JG_TECH_PARAMS_PIPELINE:
                inspectionEquipInfo.setTechParams(BeanUtil.beanToMap(equipTechParamPipelineMapper.getPipelineByDefaultValue(registrationInfo.getRecord())));
                break;
            case IDX_BIZ_JG_TECH_PARAMS_ROPEWAY:
                inspectionEquipInfo.setTechParams(BeanUtil.beanToMap(equipTechParamRopewayMapper.getRopewayByDefaultValue(registrationInfo.getRecord())));
                break;
            default:
                break;
        }
    }

    private void touchRule(InspectionEquipInfo inspectionEquipInfo) {
        if (log.isInfoEnabled()) {
            log.info("发送规则的消息对象:{}", toJSONString(inspectionEquipInfo));
        }

        RequestContext.setToken(amosRequestContext.getToken());
        RequestContext.setAppKey(amosRequestContext.getAppKey());
        RequestContext.setProduct(amosRequestContext.getProduct());
        // 2.调用规则
        try {
            ruleTrigger.publish(inspectionEquipInfo, ruleName +"/"+ inspectionEquipInfo.getBizType(), null);
        } catch (Exception e) {
            log.error("调用规则触发风险模型失败", e);
        }
    }
}
