package com.lutao.cloud.consume.factory;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.databind.JsonNode;
import com.lutao.cloud.collect.vo.DataAddVO;
import com.lutao.cloud.common.core.kafka.MessageCommandEnum;
import com.lutao.cloud.common.core.util.CollectionUtil;
import com.lutao.cloud.common.core.util.MessageInfo;
import com.lutao.cloud.consume.service.HazardousGasParametersTagService;
import com.lutao.cloud.consume.util.TimeUtil;
import com.lutao.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class HazardousGasParametersTagStrategy implements CommandStrategy<HazardousGasParametersTag> {

    @Resource
    private HazardousGasParametersTagService hazardousGasParametersTagService;

    @Resource(name = "redisTemplateAlias")
    private RedisTemplate redisTemplate;


    private static HazardousGasParametersTagStrategy hazardousGasParametersTagStrategy;

    private List<HazardousGasParametersTag> hazardousGasParametersTags = new ArrayList<>();


    @PostConstruct
    public void init() {
        hazardousGasParametersTagStrategy = this;
        hazardousGasParametersTagStrategy.hazardousGasParametersTagService = this.hazardousGasParametersTagService;
        hazardousGasParametersTagStrategy.hazardousGasParametersTags = this.hazardousGasParametersTags;
        hazardousGasParametersTagStrategy.redisTemplate = this.redisTemplate;
    }

    @Override
    public MessageInfo execute(String command, JsonNode data, DataAddVO dataAddVO) {

        if (MessageCommandEnum.MESSAGE_ADD.getCommand().equals(command)) {
            HazardousGasParametersTag hazardousGasParametersTag = JSONUtil.toBean(data.toString(), HazardousGasParametersTag.class);
            hazardousGasParametersTag.setAppId(dataAddVO.getAppId());
            add(hazardousGasParametersTag);

        } else if (MessageCommandEnum.MESSAGE_DEL.getCommand().equals(command)) {
            HazardousGasParametersTag hazardousGasParametersTag = JSONUtil.toBean(data.toString(), HazardousGasParametersTag.class);
            hazardousGasParametersTag.setAppId(dataAddVO.getAppId());
            del(hazardousGasParametersTag);


        } else if (MessageCommandEnum.MESSAGE_upd.getCommand().equals(command)) {
            HazardousGasParametersTag hazardousGasParametersTag = JSONUtil.toBean(data.toString(), HazardousGasParametersTag.class);
            hazardousGasParametersTag.setAppId(dataAddVO.getAppId());
            upd(hazardousGasParametersTag);

        } else if (MessageCommandEnum.MESSAGE_FIND.getCommand().equals(command)) {

            List<String> idList = new ArrayList<>();
            for (JsonNode node : data) {
                String id = node.get("id").asText();
                idList.add(id);
            }

            log.info("hazardousGasParametersTagStrategy 进行find操作 .......");
            List<HazardousGasParametersTag> list = hazardousGasParametersTagStrategy.hazardousGasParametersTagService.list(
                    Wrappers.lambdaQuery(HazardousGasParametersTag.class).in(HazardousGasParametersTag::getOriginId, idList)
                            .eq(HazardousGasParametersTag::getAppId, dataAddVO.getAppId())
            );
            return MessageInfo.ok(list);
        }

        return null;
    }

    @Override
    public MessageInfo executeBatch(List<DataAddVO> dataAddVOS) {
        String command = dataAddVOS.get(0).getCommand();

        List<HazardousGasParametersTag> hazardousGasParametersTags = new ArrayList<>();

        for (DataAddVO dataAddVO : dataAddVOS) {
            HazardousGasParametersTag hazardousGasParametersTag = JSONUtil.toBean(dataAddVO.getJsonDate().toString(), HazardousGasParametersTag.class);
            hazardousGasParametersTag.setAppId(dataAddVO.getAppId());
            hazardousGasParametersTags.add(hazardousGasParametersTag);
        }

        if (MessageCommandEnum.MESSAGE_ADD.getCommand().equals(command)) {
            log.info("hazardousGasParametersTagStrategy 进行add-batch操作 ......添加数量为：" + hazardousGasParametersTags.size());
            for (HazardousGasParametersTag hazardousGasParametersTag : hazardousGasParametersTags) {
                add(hazardousGasParametersTag);
            }
        } else if (MessageCommandEnum.MESSAGE_DEL.getCommand().equals(command)) {
            log.info("hazardousGasParametersTagStrategy 进行del-batch操作 .......删除数量为：" + hazardousGasParametersTags.size());
            for (HazardousGasParametersTag hazardousGasParametersTag : hazardousGasParametersTags) {
                del(hazardousGasParametersTag);
            }
        } else if (MessageCommandEnum.MESSAGE_upd.getCommand().equals(command)) {
            log.info("hazardousGasParametersTagStrategy 进行upd-batch操作 .......更新数量为：" + hazardousGasParametersTags.size());
            for (HazardousGasParametersTag hazardousGasParametersTag : hazardousGasParametersTags) {
                upd(hazardousGasParametersTag);
            }
        }

        return null;
    }

    /**
     * @Description: 指标停用
     * @Param: [java.lang.String, java.lang.String, java.lang.String]
     * @Return: void
     * @Author: vincent.zhao
     * @Date: 2024/6/20 16:01
     */
    private void stopTag(String appId, String platformCode, String tagCode) {
        //停用 接口收到指标停用的变更后， 在线率停止计算，应收到次数以变更时间为节点，计算在线率
        //启用 接口收到指标启用的变更后，如果初始化中没有，则新增，开始时间以变更时间为准，计算在线率。 如果初始化中有（一天内多次停用启用，在线率分段计算，只计算启用段内的。
        BoundHashOperations parametersTagCache = hazardousGasParametersTagStrategy.redisTemplate.boundHashOps(LocalDate.now() + ":" + PerceptionMonitorHazardousGasInfo.TABLE_NAME + ":" + appId + ":" + platformCode + ":" + tagCode);
        Integer count = (Integer) parametersTagCache.get("received_count");

        if (Objects.nonNull(count)) {
            parametersTagCache.put("end_time", LocalDateTime.now().toString());
            // 计算每分钟应该接受的数据量
            LocalDateTime beginTime = LocalDateTime.parse(parametersTagCache.get("begin_time").toString(), DateTimeFormatter.ISO_LOCAL_DATE_TIME);
            Long shouldAcceptCount = TimeUtil.getTimeDifference(beginTime, LocalDateTime.now());
            parametersTagCache.put("should_accept_count", shouldAcceptCount);
            parametersTagCache.put("enable", 1);

        }
    }

    private void startTag(String appId, String platformCode, String tagCode) {
        //停用 接口收到指标停用的变更后， 在线率停止计算，应收到次数以变更时间为节点，计算在线率
        //启用 接口收到指标启用的变更后，如果初始化中没有，则新增，开始时间以变更时间为准，计算在线率。 如果初始化中有（一天内多次停用启用，在线率分段计算，只计算启用段内的。
        BoundHashOperations parametersTagCache = hazardousGasParametersTagStrategy.redisTemplate.boundHashOps(LocalDate.now() + ":" + PerceptionMonitorHazardousGasInfo.TABLE_NAME + ":" + appId + ":" + platformCode + ":" + tagCode);
        Integer count = (Integer) parametersTagCache.get("received_count");

        if (Objects.nonNull(count) && count < 1) {
            parametersTagCache.put("should_accept_count", 0);
            parametersTagCache.put("received_count", 0);
            parametersTagCache.put("begin_time", LocalDateTime.now().toString());
            parametersTagCache.put("enable", 0);
        }else {
            //有的情况下
            parametersTagCache.put("begin_time", LocalDateTime.now().toString());
            parametersTagCache.delete("end_time");
            parametersTagCache.put("enable", 0);
        }
    }

    /**
     * @Description: 指标添加
     * @Param: [java.lang.String, java.lang.String, java.lang.String]
     * @Return: void
     * @Author: vincent.zhao
     * @Date: 2024/6/20 16:01
     */
    private void addTag(String appId, String platformCode, String tagCode) {
        BoundHashOperations parametersTagCache = hazardousGasParametersTagStrategy.redisTemplate.boundHashOps(LocalDate.now() + ":" + PerceptionMonitorHazardousGasInfo.TABLE_NAME + ":" + appId + ":" + platformCode + ":" + tagCode);
        Integer count = (Integer) parametersTagCache.get("received_count");

        if (Objects.nonNull(count)) {
            parametersTagCache.put("begin_time", LocalDateTime.now().toString());
            parametersTagCache.put("resource", PerceptionMonitorHazardousGasInfo.TABLE_NAME);
            parametersTagCache.put("received_count", 0);
            parametersTagCache.put("should_accept_count", 0);
            parametersTagCache.put("enable", 0);
            parametersTagCache.expire(48, TimeUnit.HOURS);
        }
    }

    /**
     * @Description: 添加
     * @Param: [com.lutao.entity.HazardousGasParametersTag]
     * @Return: void
     * @Author: vincent.zhao
     * @Date: 2024/6/21 15:14
     */
    private void add(HazardousGasParametersTag hazardousGasParametersTag) {
        List<HazardousGasParametersTag> tempList = hazardousGasParametersTagStrategy.hazardousGasParametersTagService.list(Wrappers.lambdaQuery(HazardousGasParametersTag.class)
                .eq(HazardousGasParametersTag::getAppId, hazardousGasParametersTag.getAppId())
                .eq(HazardousGasParametersTag::getOriginId, hazardousGasParametersTag.getOriginId()));

        // 新增指标
        if (CollectionUtil.isNotEmpty(tempList)) {
            addTag(hazardousGasParametersTag.getAppId(), hazardousGasParametersTag.getPlatformCode(), hazardousGasParametersTag.getTagCode());
        }


        log.info("hazardousGasParametersTagStrategy 进行add操作 ......");

        int count = hazardousGasParametersTagStrategy.hazardousGasParametersTagService.count(Wrappers.lambdaQuery(HazardousGasParametersTag.class).eq(HazardousGasParametersTag::getAppId, hazardousGasParametersTag.getAppId())
                .eq(HazardousGasParametersTag::getTagCode, hazardousGasParametersTag.getTagCode()));
        if (count > 1){
            //重复删除
            hazardousGasParametersTagStrategy.hazardousGasParametersTagService.remove(Wrappers.lambdaQuery(HazardousGasParametersTag.class).eq(HazardousGasParametersTag::getAppId, hazardousGasParametersTag.getAppId())
                    .eq(HazardousGasParametersTag::getTagCode, hazardousGasParametersTag.getTagCode()));
        }

        hazardousGasParametersTagStrategy.hazardousGasParametersTagService.saveOrUpdate(hazardousGasParametersTag,
                Wrappers.lambdaQuery(HazardousGasParametersTag.class)
                        .eq(HazardousGasParametersTag::getAppId, hazardousGasParametersTag.getAppId())
                        .eq(HazardousGasParametersTag::getOriginId, hazardousGasParametersTag.getOriginId()));
        //指标停用
        if ("1".equals(hazardousGasParametersTag.getStatus())) {
            stopTag(hazardousGasParametersTag.getAppId(), hazardousGasParametersTag.getPlatformCode(), hazardousGasParametersTag.getTagCode());
        }

    }

    /**
     * @Description: 更新
     * @Param: [com.lutao.entity.HazardousGasParametersTag]
     * @Return: void
     * @Author: vincent.zhao
     * @Date: 2024/6/25 15:21
     */
    private void upd(HazardousGasParametersTag hazardousGasParametersTag) {
        log.info("hazardousGasParametersTagStrategy 进行upd操作 .......");
        hazardousGasParametersTagStrategy.hazardousGasParametersTagService.update(hazardousGasParametersTag, Wrappers.lambdaQuery(HazardousGasParametersTag.class)
                .eq(HazardousGasParametersTag::getAppId, hazardousGasParametersTag.getAppId())
                .eq(HazardousGasParametersTag::getOriginId, hazardousGasParametersTag.getOriginId()));

        //指标停用
        if ("1".equals(hazardousGasParametersTag.getStatus())) {
            stopTag(hazardousGasParametersTag.getAppId(), hazardousGasParametersTag.getPlatformCode(), hazardousGasParametersTag.getTagCode());
        }
        //启用
        if ("0".equals(hazardousGasParametersTag.getStatus())) {
            startTag(hazardousGasParametersTag.getAppId(), hazardousGasParametersTag.getPlatformCode(), hazardousGasParametersTag.getTagCode());
        }
    }

    /**
     * @Description: 删除
     * @Param: [com.lutao.entity.HazardousGasParametersTag]
     * @Return: void
     * @Author: vincent.zhao
     * @Date: 2024/6/20 16:01
     */
    private void del(HazardousGasParametersTag hazardousGasParametersTag) {
        log.info("hazardousGasParametersTagStrategy 进行del操作 .......");
        hazardousGasParametersTagStrategy.hazardousGasParametersTagService.remove(Wrappers.lambdaQuery(HazardousGasParametersTag.class)
                .eq(HazardousGasParametersTag::getAppId, hazardousGasParametersTag.getAppId())
                .eq(HazardousGasParametersTag::getOriginId, hazardousGasParametersTag.getOriginId()));

        //指标停用
        stopTag(hazardousGasParametersTag.getAppId(), hazardousGasParametersTag.getPlatformCode(), hazardousGasParametersTag.getTagCode());
    }

}
