package com.lutao.cloud.oil.controller;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
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.CollectLogService;
import com.lutao.cloud.oil.service.PlatformInfoService;
import com.lutao.cloud.oil.service.TagOnlineRateTodayService;
import com.lutao.cloud.oil.util.Base64Utils;
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.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;

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

    @Resource
    private TagOnlineRateTodayService tagOnlineRateTodayService;

    @Resource
    private PlatformInfoService platformInfoService;

    @Resource
    private CollectLogService collectLogService;

    @PostMapping("/car")
    @Inner(value = false)
    public String car(@RequestBody String object) {
        try {
            //String json = parseQueryStringToJson(object);
            log.info("object{}",object);
//            CollectLog collectLog = new CollectLog();
//            collectLog.setData(object);
//            collectLog.setCollectNumber(object.length());

            int chunkSize = 10000; // 可以根据实际情况调整分块大小
            List<String> chunks = splitStringIntoChunks(object, chunkSize);

            StringBuilder result = new StringBuilder();
            for (String chunk : chunks) {
                result.append(chunk);
            }
            log.info("result::={}",result.toString());
            String s = parseQueryStringToJson(result.toString());
            log.info("json:{}",s);

            JSONObject jsonObject = JSONUtil.parseObj(s);
            String closeup_pic = jsonObject.getStr("closeup_pic");
            if (closeup_pic != null){
                closeup_pic =closeup_pic
                        .replace('-', '+')
                        .replace('_', '/')
                        .replace('.', '=');
                jsonObject.set("closeup_pic", closeup_pic);
                String picture = jsonObject.getStr("picture");
                picture = picture
                        .replace('-', '+')
                        .replace('_', '/')
                        .replace('.', '=');
                jsonObject.set("picture", picture);
//                collectLog.setData(jsonObject.toString());
//                collectLogService.save(collectLog);
            }
            return result.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private List<String> splitStringIntoChunks(String str, int chunkSize) {
        List<String> chunks = new ArrayList<>();
        int length = str.length();
        for (int start = 0; start < length; start += chunkSize) {
            int end = Math.min(start + chunkSize, length);
            chunks.add(str.substring(start, end));
        }
        return chunks;
    }

    public static String parseQueryStringToJson(String queryString) throws UnsupportedEncodingException {
        Map<String, String> params = new LinkedHashMap<>();

        // 按照 & 分割字符串
        String[] pairs = queryString.split("&");

        for (String pair : pairs) {
            // 按照 = 分割键值对
            int idx = pair.indexOf("=");
            String key = URLDecoder.decode(pair.substring(0, idx), "UTF-8");
            String value = URLDecoder.decode(pair.substring(idx + 1), "UTF-8");

            params.put(key, value);
        }

        // 将 Map 转换为 JSON 字符串
        ObjectMapper mapper = new ObjectMapper();
        try {
            return mapper.writeValueAsString(params);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

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

    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");
        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对象

                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对象

                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对象

                tagOnlineRate = processHazardousGasInfo(hazardousGasInfo, tagOnlineRate, platformMap, receivedCount, beginTime, endTime, resource, shouldAcceptCount);
                break;
            case "perception_monitor_info":
                PerceptionMonitorInfo monitorInfo = JSONUtil.toBean(entity, PerceptionMonitorInfo.class); // 将JSON字符串转换为Java对象

                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(), 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(), 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(), 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) {
            return fillTagOnlineRate(monitorInfo.getAppId(), monitorInfo.getPlatformCode(), monitorInfo.getTagId(), monitorInfo.getTagCode(), monitorInfo.getTagName(), tagOnlineRate, platformMap, receivedCount, beginTime, endTime, resource, shouldAcceptCount);
        } else return null;
    }


    private TagOnlineRateToday fillTagOnlineRate(String appId, String platformCode, String tagId, String tagCode, String tagName, 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.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(String.valueOf(LocalDate.now()));
        return tagOnlineRate;
    }
}
