package com.lutao.cloud.oil.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.lutao.cloud.common.security.annotation.Inner;
import com.lutao.cloud.oil.pojo.entity.TagOnlineRate;
import com.lutao.cloud.oil.pojo.entity.TagOnlineRateToday;
import com.lutao.cloud.oil.service.*;
import com.lutao.entity.*;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/process-tag-today")
public class ProcessTagController {
    @Resource(name = "redisTemplateAlias")
    private RedisTemplate redisTemplate;

    @Resource
    private TagOnlineRateTodayService tagOnlineRateTodayService;

    @Resource
    private PlatformInfoService platformInfoService;

    @Resource
    private CollectLogService collectLogService;

    @Resource
    private ProcessParameterTagService processParameterTagService;

    @Resource
    private FireParametersTagService fireParametersTagService;

    @Resource
    private GasParametersTagService gasParametersTagService;

    @Resource
    private HazardousGasParametersTagService hazardousGasParametersTagService;


    @PostMapping("/init")
    @Inner(value = false)
    public void initToday() {
        execute();
    }

    @PostMapping("/init-tagInfo")
    @Inner(value = false)
    public void initTagInfo() {
        initProcess();
    }

    public void initProcess() {
            try {
                String currentTime = LocalDateTime.now().toString();
                List<FireParametersTag> fireParametersTags = fireParametersTagService
                        .list(Wrappers.lambdaQuery(FireParametersTag.class)
                                .isNotNull(FireParametersTag::getTagCode)
                                .isNotNull(FireParametersTag::getPlatformCode)
                                .isNotNull(FireParametersTag::getAppId)
                                .eq(FireParametersTag::getStatus, "0"));
                for (FireParametersTag fireParametersTag : fireParametersTags) {
                    BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(LocalDate.now() + ":"
                            + PerceptionMonitorFireInfo.TABLE_NAME
                            + ":" + fireParametersTag.getAppId()
                            + ":" + fireParametersTag.getPlatformCode()
                            + ":" + fireParametersTag.getTagCode());
                    boundHashOperations.put("tagInfo", JSONUtil.toJsonStr(fireParametersTag));
                }

                List<GasParametersTag> gasParametersTags = gasParametersTagService
                        .list(Wrappers.lambdaQuery(GasParametersTag.class)
                                .isNotNull(GasParametersTag::getTagCode)
                                .isNotNull(GasParametersTag::getPlatformCode)
                                .isNotNull(GasParametersTag::getAppId)
                                .eq(GasParametersTag::getStatus, "0"));
                for (GasParametersTag gasParametersTag : gasParametersTags) {
                    BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(LocalDate.now()
                            + ":" + PerceptionMonitorGasInfo.TABLE_NAME
                            + ":" + gasParametersTag.getAppId()
                            + ":" + gasParametersTag.getPlatformCode()
                            + ":" + gasParametersTag.getTagCode());
                    boundHashOperations.put("tagInfo", JSONUtil.toJsonStr(gasParametersTag));
                }

                List<HazardousGasParametersTag> hazardousGasParametersTags = hazardousGasParametersTagService
                        .list(Wrappers.lambdaQuery(HazardousGasParametersTag.class)
                                .isNotNull(HazardousGasParametersTag::getTagCode)
                                .isNotNull(HazardousGasParametersTag::getPlatformCode)
                                .isNotNull(HazardousGasParametersTag::getAppId)
                                .eq(HazardousGasParametersTag::getStatus, "0"));

                for (HazardousGasParametersTag hazardousGasParametersTag : hazardousGasParametersTags) {
                    BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(LocalDate.now()
                            + ":" + PerceptionMonitorHazardousGasInfo.TABLE_NAME
                            + ":" + hazardousGasParametersTag.getAppId()
                            + ":" + hazardousGasParametersTag.getPlatformCode()
                            + ":" + hazardousGasParametersTag.getTagCode());
                    boundHashOperations.put("tagInfo", JSONUtil.toJsonStr(hazardousGasParametersTag));
                }

                List<ProcessParameterTag> processParameterTags = processParameterTagService
                        .list(Wrappers.lambdaQuery(ProcessParameterTag.class)
                                .isNotNull(ProcessParameterTag::getTagCode)
                                .isNotNull(ProcessParameterTag::getPlatformCode)
                                .isNotNull(ProcessParameterTag::getAppId)
                                .eq(ProcessParameterTag::getStatus, "0"));
                for (ProcessParameterTag processParameterTag : processParameterTags) {
                    BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(LocalDate.now()
                            + ":" + PerceptionMonitorInfo.TABLE_NAME
                            + ":" + processParameterTag.getAppId()
                            + ":" + processParameterTag.getPlatformCode()
                            + ":" + processParameterTag.getTagCode());
                    boundHashOperations.put("tagInfo", JSONUtil.toJsonStr(processParameterTag));
                }
            }catch (Exception e){
                CollectLog collectLog = new CollectLog();
                collectLog.setCommand("error");
                collectLog.setData("tag_online_rate==error==" + e.getMessage());
                e.printStackTrace();
                collectLogService.save(collectLog);
            }



    }

    private void execute() {
        try {
            long startTime = System.currentTimeMillis();
            //方法执行  调用删除
            tagOnlineRateTodayService.remove(null);

            //当天
            Set<String> redisKeys = redisTemplate.keys(LocalDate.now() + "*");
            List<PlatformInfo> platformInfos = platformInfoService.list();

            Map<String, PlatformInfo> platformMap = new HashMap<>();
            for (PlatformInfo platformInfo : platformInfos) {
                platformMap.put(platformInfo.getPlatformCode(), platformInfo);
            }
            if (redisKeys == null) {
                return;
            }
            for (String key : redisKeys) {
                processKey(key, platformMap);
            }
            long endTime = System.currentTimeMillis();
            long executionTime = endTime - startTime; //milliseconds
            String executionTimeStr = String.format("%d milliseconds", executionTime);
            CollectLog collectLog = new CollectLog();
            collectLog.setCommand("tag_online_rate");
            collectLog.setData(executionTimeStr);
            collectLogService.save(collectLog);

        } catch (Exception e) {
            CollectLog collectLog = new CollectLog();
            collectLog.setCommand("error");
            collectLog.setData("tag_online_rate==error==" + e.getMessage());
            e.printStackTrace();
            collectLogService.save(collectLog);
        }
    }

    private void processKey(String key, Map<String, PlatformInfo> platformMap) {

        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(key);
        String resource = (String) boundHashOperations.get("resource");
        Integer receivedCount = Optional.ofNullable((Integer) boundHashOperations.get("received_count")).orElse(0);
        String entity = (String) boundHashOperations.get("entity");
        String tagInfo = (String) boundHashOperations.get("tagInfo");
        LocalDateTime beginTime = parseDateTime((String) boundHashOperations.get("begin_time"));
        LocalDateTime endTime = parseDateTime((String) boundHashOperations.get("end_time"));
        Integer shouldAcceptCount = Optional.ofNullable((Integer) boundHashOperations.get("should_accept_count")).orElse(0);

        TagOnlineRateToday tagOnlineRate = new TagOnlineRateToday();
        switch (Objects.requireNonNull(resource)) {
            case "perception_monitor_fire_info":
                PerceptionMonitorFireInfo fireInfo = JSONUtil.toBean(entity, PerceptionMonitorFireInfo.class); // 将JSON字符串转换为Java对象
                if (fireInfo.getTagCode() == null){
                    FireParametersTag fireParametersTag = JSONUtil.toBean(tagInfo, FireParametersTag.class);
                    fireInfo = new PerceptionMonitorFireInfo();
                    BeanUtil.copyProperties(fireParametersTag, fireInfo);
                }
                tagOnlineRate = processFireInfo(fireInfo, tagOnlineRate, platformMap, receivedCount, beginTime, endTime, resource, shouldAcceptCount);
                break;
            case "perception_monitor_gas_info":
                PerceptionMonitorGasInfo gasInfo = JSONUtil.toBean(entity, PerceptionMonitorGasInfo.class); // 将JSON字符串转换为Java对象
                if (gasInfo.getTagCode() == null){
                    GasParametersTag gasParametersTag = JSONUtil.toBean(tagInfo, GasParametersTag.class);
                    gasInfo = new PerceptionMonitorGasInfo();
                    BeanUtil.copyProperties(gasParametersTag, gasInfo);
                }

                tagOnlineRate = processGasInfo(gasInfo, tagOnlineRate, platformMap, receivedCount, beginTime, endTime, resource, shouldAcceptCount);
                break;
            case "perception_monitor_hazardous_gas_info":
                PerceptionMonitorHazardousGasInfo hazardousGasInfo = JSONUtil.toBean(entity, PerceptionMonitorHazardousGasInfo.class); // 将JSON字符串转换为Java对象
                if (hazardousGasInfo.getTagCode() == null){
                    HazardousGasParametersTag hazardousGasParametersTag = JSONUtil.toBean(tagInfo, HazardousGasParametersTag.class);
                    hazardousGasInfo = new PerceptionMonitorHazardousGasInfo();
                    BeanUtil.copyProperties(hazardousGasParametersTag, hazardousGasInfo);
                }
                tagOnlineRate = processHazardousGasInfo(hazardousGasInfo, tagOnlineRate, platformMap, receivedCount, beginTime, endTime, resource, shouldAcceptCount);
                break;
            case "perception_monitor_info":
                PerceptionMonitorInfo monitorInfo = JSONUtil.toBean(entity, PerceptionMonitorInfo.class); // 将JSON字符串转换为Java对象
                if (monitorInfo.getTagCode() == null){
                    ProcessParameterTag processParameterTag = JSONUtil.toBean(tagInfo, ProcessParameterTag.class);
                    monitorInfo = new PerceptionMonitorInfo();
                    BeanUtil.copyProperties(processParameterTag, monitorInfo);
                }
                tagOnlineRate = processMonitorInfo(monitorInfo, tagOnlineRate, platformMap, receivedCount, beginTime, endTime, resource, shouldAcceptCount);
                break;
            default:
                break;
        }
        tagOnlineRateTodayService.save(tagOnlineRate);
    }

    private LocalDateTime parseDateTime(String dateTimeStr) {
        List<String> formats = Arrays.asList(
                "yyyy-MM-dd'T'HH:mm:ss",
                "yyyy-MM-dd'T'HH:mm:ss.SSS"
        );
        LocalDateTime dateTime = null;
        if (dateTimeStr != null) {
            for (String format : formats) {
                try {
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);
                    dateTime = LocalDateTime.parse(dateTimeStr, formatter);
                    break;
                } catch (DateTimeParseException e) {
                    // Ignore and try the next format
                }
            }
        }
        return dateTime;
    }

    private TagOnlineRateToday processFireInfo(PerceptionMonitorFireInfo fireInfo, TagOnlineRateToday tagOnlineRate, Map<String, PlatformInfo> platformMap, Integer receivedCount, LocalDateTime beginTime, LocalDateTime endTime, String resource, Integer shouldAcceptCount) {
        if (fireInfo != null) {
            return fillTagOnlineRate(fireInfo.getAppId(), fireInfo.getPlatformCode(), fireInfo.getTagId(), fireInfo.getTagCode(), fireInfo.getTagName(), "6", tagOnlineRate, platformMap, receivedCount, beginTime, endTime, resource, shouldAcceptCount);
        } else return null;
    }

    private TagOnlineRateToday processGasInfo(PerceptionMonitorGasInfo gasInfo, TagOnlineRateToday tagOnlineRate, Map<String, PlatformInfo> platformMap, Integer receivedCount, LocalDateTime beginTime, LocalDateTime endTime, String resource, Integer shouldAcceptCount) {
        if (gasInfo != null) {
            return fillTagOnlineRate(gasInfo.getAppId(), gasInfo.getPlatformCode(), gasInfo.getTagId(), gasInfo.getTagCode(), gasInfo.getTagName(), "7", tagOnlineRate, platformMap, receivedCount, beginTime, endTime, resource, shouldAcceptCount);
        } else return null;
    }

    private TagOnlineRateToday processHazardousGasInfo(PerceptionMonitorHazardousGasInfo hazardousGasInfo, TagOnlineRateToday tagOnlineRate, Map<String, PlatformInfo> platformMap, Integer receivedCount, LocalDateTime beginTime, LocalDateTime endTime, String resource, Integer shouldAcceptCount) {
        if (hazardousGasInfo != null) {
            return fillTagOnlineRate(hazardousGasInfo.getAppId(), hazardousGasInfo.getPlatformCode(), hazardousGasInfo.getTagId(), hazardousGasInfo.getTagCode(), hazardousGasInfo.getTagName(), "8", tagOnlineRate, platformMap, receivedCount, beginTime, endTime, resource, shouldAcceptCount);
        } else return null;
    }

    private TagOnlineRateToday processMonitorInfo(PerceptionMonitorInfo monitorInfo, TagOnlineRateToday tagOnlineRate, Map<String, PlatformInfo> platformMap, Integer receivedCount, LocalDateTime beginTime, LocalDateTime endTime, String resource, Integer shouldAcceptCount) {
            if (monitorInfo != null) {
                ProcessParameterTag processParameterTag = processParameterTagService.getOne(Wrappers.lambdaQuery(ProcessParameterTag.class).eq(ProcessParameterTag::getTagCode, monitorInfo.getTagCode()).eq(ProcessParameterTag::getAppId, monitorInfo.getAppId()));
                String tagType = "";
                if (processParameterTag != null) {
                    tagType = processParameterTag.getTagType();
                }
            return fillTagOnlineRate(monitorInfo.getAppId(), monitorInfo.getPlatformCode(), monitorInfo.getTagId(), monitorInfo.getTagCode(), monitorInfo.getTagName(), tagType, tagOnlineRate, platformMap, receivedCount, beginTime, endTime, resource, shouldAcceptCount);
        } else return null;
    }


    private TagOnlineRateToday fillTagOnlineRate(String appId, String platformCode, String tagId, String tagCode, String tagName, String tagType, TagOnlineRateToday tagOnlineRate, Map<String, PlatformInfo> platformMap, Integer receivedCount, LocalDateTime beginTime, LocalDateTime endTime, String resource, Integer shouldAcceptCount) {
        tagOnlineRate.setAppId(appId);
        tagOnlineRate.setPlatformCode(platformCode);
        PlatformInfo platformInfo = platformMap.get(platformCode);
        if (platformInfo != null) {
            tagOnlineRate.setOilGasName(platformMap.get(platformCode).getOilGasName());
            tagOnlineRate.setPlatformName(platformMap.get(platformCode).getPlatformName());
            tagOnlineRate.setOperatingCompany(platformMap.get(platformCode).getOperatingCompany());
        }
        tagOnlineRate.setTagId(tagId);
        tagOnlineRate.setTagCode(tagCode);
        tagOnlineRate.setTagName(tagName);
        tagOnlineRate.setTagType(tagType);
        tagOnlineRate.setBeginTime(beginTime);
        tagOnlineRate.setEndTime(endTime);
        tagOnlineRate.setReceiveCount(receivedCount);
        tagOnlineRate.setShouldReceiveCount(shouldAcceptCount);
        if (shouldAcceptCount == 0) {
            shouldAcceptCount = 143;
        }
        tagOnlineRate.setOnlineRate(receivedCount != null ? String.valueOf((float) receivedCount / shouldAcceptCount) : "0");
        tagOnlineRate.setResourceTable(resource);
        tagOnlineRate.setCreateTime(LocalDateTime.now());
        tagOnlineRate.setUpdateTime(LocalDateTime.now());
        tagOnlineRate.setDataDate(LocalDate.now().toString());
        return tagOnlineRate;
    }
}
