package com.microservices.mon.k8s.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.context.SecurityContextHolder;
import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.core.utils.StringUtils;
import com.microservices.mon.k8s.domain.*;
import com.microservices.mon.k8s.domain.vo.*;
import com.microservices.mon.k8s.service.IK8sDashboardService;
import com.microservices.mon.k8s.service.IMonCommonAsyncService;
import com.microservices.mon.k8s.utils.PromQLConstant;
import com.microservices.mon.k8s.utils.RancherResponseHandler;
import com.microservices.mon.k8s.utils.SkywalkingGQLConstant;
import com.microservices.system.api.RemoteGatewayService;
import com.microservices.system.api.RemoteRancherService;
import com.microservices.system.api.model.GraphqlQueryVo;
import feign.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@RefreshScope
public class K8SDashboardServiceImpl extends CommonService implements IK8sDashboardService {
    @Autowired
    private RemoteRancherService remoteRancherService;
    @Autowired
    private IMonCommonAsyncService monCommonAsyncService;
    @Autowired
    private RemoteGatewayService remoteGatewayService;

    @Override
    public List<K8sNamespace> getNamespaceDetailList(boolean needPod, String search) {
        return monCommonAsyncService.getNamespaceDetailList(needPod, search);
    }

    @Override
    public List<K8sClusterNode> getClusterNodeList() {
        List<RancherClusterNodeVo> rancherClusterNodeVoList;
        //调用rancher远程接口获取集群节点列表
        JSONObject clusterNodeJsonObject = RancherResponseHandler.handleJsonObject(remoteRancherService.getK8sClusterNodeList(cluster_id, SecurityContextHolder.getUserKey()), "获取K8S集群节点");
        if (clusterNodeJsonObject != null && clusterNodeJsonObject.containsKey("data")) {
            rancherClusterNodeVoList = clusterNodeJsonObject.getJSONArray("data").toList(RancherClusterNodeVo.class);
            return rancherClusterNodeVoList.stream().map(RancherClusterNodeVo::toK8sClusterNode).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    @Override
    public List<String> getApplicationPodIdList(String kind, String namespace, String applicationName) {
        ApplicationType applicationType = ApplicationType.getApplicationTypeByKey(kind);
        JSONObject applicationJson = RancherResponseHandler.handleJsonObject(remoteRancherService.getK8sApplicationDetail(cluster_id, applicationType.getFullName(), namespace, applicationName, SecurityContextHolder.getUserKey()), "获取应用详情");
        RancherApplicationVo rancherApplicationVo = applicationJson.toJavaObject(RancherApplicationVo.class);
        if (rancherApplicationVo != null && rancherApplicationVo.getMetadata() != null && rancherApplicationVo.getMetadata().getRelationships() != null) {
            JSONArray relationships = rancherApplicationVo.getMetadata().getRelationships();
            for (int i = 0; i < relationships.size(); i++) {
                JSONObject relationship = relationships.getJSONObject(i);
                if (relationship.containsKey("toType") && "pod".equals(relationship.getString("toType"))) {
                    String selector = relationship.getString("selector");
                    if (StringUtils.isNotEmpty(selector) && selector.contains("app=")) {
                        String appName = selector.substring(selector.indexOf("=") + 1);
                        JSONObject podListJson = RancherResponseHandler.handleJsonObject(remoteRancherService.getK8sPodListByNamespace(cluster_id, namespace, SecurityContextHolder.getUserKey()), "获取容器列表");
                        if (podListJson != null && podListJson.containsKey("data")) {
                            List<RancherPodVo> rancherPodVoList = podListJson.getJSONArray("data").toList(RancherPodVo.class);
                            List<RancherPodVo> applicationToPodList = rancherPodVoList.stream()
                                    .filter(rancherPodVo -> rancherPodVo.getMetadata().getLabels().containsKey("app") && rancherPodVo.getMetadata().getLabels().get("app").equals(appName))
                                    .collect(Collectors.toList());
                            return applicationToPodList.stream().map(x -> x.getStatus().getPodIP()).collect(Collectors.toList());
                        }
                    }
                }
            }
        }
        return Collections.emptyList();
    }

    @Override
    public K8sClusterStatus getClusterStatus() {
        return monCommonAsyncService.getClusterStatus(PromQLConstant.CLUSTER_NODE_COUNT(cluster_id));
    }

    @Override
    public List<MetricCommonData> getClusterQps() {
        Date now = DateUtils.getNowDate();
        long endTime = now.getTime() / 1000;
        // 开始时间为当前时间减去1小时
        Long startTime = now.getTime() / 1000 - 60 * 60;
        JSONObject metricResJson = remoteGatewayService.getPrometheusQueryRangeRes(PromQLConstant.CLUSTER_QPS, 14L, startTime, endTime, SecurityContextHolder.getUserKey());
        List<MetricCommonData> metricCommonDataList = getMetricCommonDataList(metricResJson);
        if (metricCommonDataList.isEmpty()) {
            for (int i = 0; i < 7; i++) {
                MetricCommonData metricCommonData = new MetricCommonData();
                metricCommonData.setDate(new Date(endTime * 1000));
                metricCommonData.setValue(0F);
                metricCommonDataList.add(metricCommonData);
                endTime -= 60 * 10;
            }
        }
        metricCommonDataList.sort(Comparator.comparing(MetricCommonData::getDate));
        return metricCommonDataList;
    }

    @Override
    public List<ApplicationRequestCountData> getApplicationRequestCount() {
        List<ApplicationRequestCountData> applicationRequestCountDataList = new ArrayList<>();
        HashMap<String, String> portMap = new HashMap<>();
        JSONObject nginxSvcJson = RancherResponseHandler.handleJsonObject(remoteRancherService.getK8sServiceByApplicationId(cluster_id, nginxApplicationId, SecurityContextHolder.getUserKey()), "获取统一请求入口服务");
        if (nginxSvcJson != null) {
            RancherServiceVo rancherServiceVo = nginxSvcJson.toJavaObject(RancherServiceVo.class);
            for (RancherServicePortsVo rancherServicePortsVo : rancherServiceVo.getSpec().getPorts()) {
                // 获取端口描述
                String portAlias = rancherServiceVo.getMetadata().getAnnotations().getString(rancherServicePortsVo.getName());
                portMap.put(String.valueOf(rancherServicePortsVo.getPort()), portAlias);
            }
        }
        JSONObject applicationRequestCountJson = remoteGatewayService.getPrometheusQueryRes(PromQLConstant.APPLICATION_REQUEST_COUNT, SecurityContextHolder.getUserKey());
        if (applicationRequestCountJson != null) {
            PrometheusResVo prometheusResVo = applicationRequestCountJson.toJavaObject(PrometheusResVo.class);
            if (prometheusResVo != null && prometheusResVo.isSuccess()) {
                List<PrometheusResultVo> resultList = prometheusResVo.getData().getResult();
                int number = 1;
                for (PrometheusResultVo result : resultList) {
                    ApplicationRequestCountData applicationRequestCountData = new ApplicationRequestCountData();
                    applicationRequestCountData.setNumber(number++);
                    JSONObject metric = result.getMetric();
                    String port = metric.getString("server_port");
                    applicationRequestCountData.setApplicationAlias(port);
                    if (portMap.containsKey(port)) {
                        applicationRequestCountData.setApplicationAlias(portMap.get(port));
                    }
                    Long value = result.getValue().getLongValue(1);
                    applicationRequestCountData.setRequestCount(value);
                    applicationRequestCountDataList.add(applicationRequestCountData);
                }
            }
        }
        return applicationRequestCountDataList;
    }

    @Override
    public K8sPodContainerStatus getPodContainerStatus(String podName) {
        K8sPodContainerStatus k8sPodContainerStatus = new K8sPodContainerStatus();
        k8sPodContainerStatus.setPodName(podName);
        JSONObject cpuUsageJson = remoteGatewayService.getPrometheusQueryRes(PromQLConstant.POD_CPU_USAGE(podName), SecurityContextHolder.getUserKey());
        PrometheusResVo cpuPrometheusResVo = cpuUsageJson.toJavaObject(PrometheusResVo.class);
        if (cpuPrometheusResVo != null && cpuPrometheusResVo.isSuccess()) {
            PrometheusResultVo result = cpuPrometheusResVo.getData().getResult().get(0);
            k8sPodContainerStatus.setCpuUsage(result.getValue().getFloatValue(1));
        }
        JSONObject memoryUsageJson = remoteGatewayService.getPrometheusQueryRes(PromQLConstant.POD_MEMORY_USAGE(podName), SecurityContextHolder.getUserKey());
        PrometheusResVo memoryPrometheusResVo = memoryUsageJson.toJavaObject(PrometheusResVo.class);
        if (memoryPrometheusResVo != null && memoryPrometheusResVo.isSuccess()) {
            PrometheusResultVo result = memoryPrometheusResVo.getData().getResult().get(0);
            Long memoryByte = result.getValue().getLong(1);
            float memoryMb = (float) memoryByte / 1024 / 1024;
            if (memoryMb > 1024) {
                k8sPodContainerStatus.setMemoryUsage(String.format("%.2f GiB", memoryMb / 1024));
            } else {
                k8sPodContainerStatus.setMemoryUsage(String.format("%.2f mib", memoryMb));
            }
        }
        return k8sPodContainerStatus;
    }

    @Override
    public K8sNodeStatus getNodeStatus(String nodeIp) {
        K8sNodeStatus k8sNodeStatus = new K8sNodeStatus();
        k8sNodeStatus.setNodeIp(nodeIp);
        JSONObject cpuUsageJson = remoteGatewayService.getPrometheusQueryRes(PromQLConstant.NODE_CPU_USAGE(nodeIp), SecurityContextHolder.getUserKey());
        PrometheusResVo cpuPrometheusResVo = cpuUsageJson.toJavaObject(PrometheusResVo.class);
        if (cpuPrometheusResVo != null && cpuPrometheusResVo.isSuccess()) {
            PrometheusResultVo result = cpuPrometheusResVo.getData().getResult().get(0);
            k8sNodeStatus.setCpuUsage(result.getValue().getFloatValue(1));
        }
        JSONObject memoryUsageJson = remoteGatewayService.getPrometheusQueryRes(PromQLConstant.NODE_MEMORY_USAGE(nodeIp), SecurityContextHolder.getUserKey());
        PrometheusResVo memoryPrometheusResVo = memoryUsageJson.toJavaObject(PrometheusResVo.class);
        if (memoryPrometheusResVo != null && memoryPrometheusResVo.isSuccess()) {
            PrometheusResultVo result = memoryPrometheusResVo.getData().getResult().get(0);
            k8sNodeStatus.setMemoryUsage(result.getValue().getFloatValue(1));
        }
        return k8sNodeStatus;
    }

    @Override
    public List<ApplicationFunction> getApplicationFunction(String kind, String namespace, String applicationName, String podIpList) {
        ApplicationType applicationType = ApplicationType.getApplicationTypeByKey(kind);
        List<ApplicationFunction> applicationFunctionsList = new ArrayList<>();
        JSONObject applicationJson = RancherResponseHandler.handleJsonObject(remoteRancherService.getK8sApplicationDetail(cluster_id, applicationType.getFullName(), namespace, applicationName, SecurityContextHolder.getUserKey()), "获取应用详情");
        if (applicationJson == null) {
            return applicationFunctionsList;
        }
        RancherApplicationVo rancherApplicationVo = applicationJson.toJavaObject(RancherApplicationVo.class);
        if (rancherApplicationVo != null) {
            K8sApplication k8sApplication = rancherApplicationVo.toK8sApplication();
            // 所有应用添加启停管理功能
            ApplicationFunction applicationFunction = new ApplicationFunction();
            applicationFunction.setKeyAndName(ApplicationFunctionType.START_AND_STOP_MANAGEMENT);
            JSONObject functionVariables = new JSONObject();
            functionVariables.put("namespace", namespace);
            functionVariables.put("applicationName", applicationName);
            functionVariables.put("operationList", ApplicationStartAndStopType.getOperationList(kind, k8sApplication));
            applicationFunction.setVariables(functionVariables);
            applicationFunctionsList.add(applicationFunction);

            // 根据应用POD Ip在Nacos上检查监听的配置列表，如果存在配置则增加配置管理按钮
            List<JSONObject> configList = new ArrayList<>();
            String[] podIpStr = podIpList.split(",");
            for (String podIp : podIpStr) {
                JSONObject nacosConfigListResJson = remoteGatewayService.getNacosConfigList(podIp, SecurityContextHolder.getUserKey());
                if (nacosConfigListResJson.containsKey("collectStatus") && 200 == nacosConfigListResJson.getIntValue("collectStatus")) {
                    JSONObject nacosConfigListJson = nacosConfigListResJson.getJSONObject("lisentersGroupkeyStatus");
                    for (String key : nacosConfigListJson.keySet()) {
                        String nacosConfigMd5 = nacosConfigListJson.getString(key);
                        if (!StringUtils.isEmpty(nacosConfigMd5) && configList.stream().noneMatch(x -> nacosConfigMd5.equals(x.getString("configMd5")))) {
                            String[] configNames = key.split("\\+");
                            JSONObject config = new JSONObject();
                            config.put("configName", configNames[0]);
                            config.put("configMd5", nacosConfigMd5);
                            config.put("configGroup", configNames[1]);
                            configList.add(config);
                        }
                    }
                }
            }
            if (!configList.isEmpty()) {
                // 检查应用是否有配置管理功能
                applicationFunction = new ApplicationFunction();
                applicationFunction.setKeyAndName(ApplicationFunctionType.CONFIGURATION_MANAGEMENT);
                functionVariables = new JSONObject();
                functionVariables.put("configList", configList);
                applicationFunction.setVariables(functionVariables);
                applicationFunctionsList.add(applicationFunction);
            }


            if (rancherApplicationVo.getMetadata() != null && rancherApplicationVo.getMetadata().getLabels() != null) {
                JSONObject LabelsJson = rancherApplicationVo.getMetadata().getLabels();
                for (String key : LabelsJson.keySet()) {
                    String k8sLabelValue = LabelsJson.getString(key);
                    ApplicationFunctionType applicationFunctionType = ApplicationFunctionType.getByLabelsKey(key);
                    if (applicationFunctionType != null) {
                        switch (applicationFunctionType) {
                            case LINK_TRACKING:
                                // 处理应用链路追踪功能相关逻辑
                                GraphqlQueryVo gqlQueryVo = SkywalkingGQLConstant.getAllServicesByGroup(skywalkingGroup);
                                JSONObject skywalkingServices = remoteGatewayService.executeSkywalkingGql(gqlQueryVo);
                                if (skywalkingServices != null
                                        && skywalkingServices.getJSONObject("data") != null
                                        && skywalkingServices.getJSONObject("data").getJSONArray(gqlQueryVo.getOperationName()) != null) {
                                    JSONArray skywalkingServicesArray = skywalkingServices.getJSONObject("data").getJSONArray(gqlQueryVo.getOperationName());
                                    for (int i = 0; i < skywalkingServicesArray.size(); i++) {
                                        JSONObject skywalkingService = skywalkingServicesArray.getJSONObject(i);
                                        if (k8sLabelValue.equals(skywalkingService.getString("shortName"))) {
                                            applicationFunction = new ApplicationFunction();
                                            applicationFunction.setKeyAndName(applicationFunctionType);
                                            functionVariables = new JSONObject();
                                            functionVariables.put("serviceId", skywalkingService.getString("id"));
                                            applicationFunction.setVariables(functionVariables);
                                            applicationFunctionsList.add(applicationFunction);
                                        }
                                    }
                                }
                                break;
                            case FLOW_CONTROL:
                                // 处理应用流量控制功能相关逻辑
                                JSONArray sentinelAppListArray = getSentinelAppList();
                                for (int i = 0; i < sentinelAppListArray.size(); i++) {
                                    JSONObject sentinelApp = sentinelAppListArray.getJSONObject(i);
                                    if (k8sLabelValue.equals(sentinelApp.getString("app"))) {
                                        applicationFunction = new ApplicationFunction();
                                        applicationFunction.setKeyAndName(applicationFunctionType);
                                        functionVariables = new JSONObject();
                                        functionVariables.put("app", k8sLabelValue);
                                        functionVariables.put("appType", sentinelApp.getLongValue("appType"));
                                        applicationFunction.setVariables(functionVariables);
                                        applicationFunctionsList.add(applicationFunction);
                                    }
                                }
                                break;
                            case REGISTRATION_CENTER:
                                // 处理应用注册中心功能相关逻辑
                                JSONObject nacosServiceList = remoteGatewayService.getNacosServiceList(k8sLabelValue, SecurityContextHolder.getUserKey());
                                if (nacosServiceList != null && nacosServiceList.getJSONArray("serviceList") != null && !nacosServiceList.getJSONArray("serviceList").isEmpty()) {
                                    JSONArray nacosServiceListArray = nacosServiceList.getJSONArray("serviceList");
                                    for (int i = 0; i < nacosServiceListArray.size(); i++) {
                                        JSONObject nacosService = nacosServiceListArray.getJSONObject(i);
                                        if (k8sLabelValue.equals(nacosService.getString("name"))) {
                                            applicationFunction = new ApplicationFunction();
                                            applicationFunction.setKeyAndName(applicationFunctionType);
                                            functionVariables = new JSONObject();
                                            functionVariables.put("name", k8sLabelValue);
                                            applicationFunction.setVariables(functionVariables);
                                            applicationFunctionsList.add(applicationFunction);
                                        }
                                    }
                                }
                                break;
                            case GATEWAY_MANAGEMENT:
                                // 处理应用网关管理功能相关逻辑
                                applicationFunction = new ApplicationFunction();
                                applicationFunction.setKeyAndName(applicationFunctionType);
                                functionVariables = new JSONObject();
                                functionVariables.put("dataId", nacosGatewayConfigId);
                                functionVariables.put("group", nacosDefaultGroup);
                                applicationFunction.setVariables(functionVariables);
                                applicationFunctionsList.add(applicationFunction);
                                break;
                        }
                    }
                }
            }
        }
        return applicationFunctionsList;
    }

    @Override
    public List<K8sNamespace> getK8sNamespaceList() {
        List<K8sNamespace> k8sNamespaceList = new ArrayList<>();
//        List<RancherNamespaceVo> rancherNamespaceVoList;
        //调用rancher远程接口获取所有命名空间列表
        boolean isNative = false;
        Response response = remoteRancherService.getK8sNamespaceList(cluster_id, SecurityContextHolder.getUserKey());
        if (response.status() == 404) {
            isNative = true;
            response = remoteRancherService.getK8sNamespaceListNative(cluster_id, SecurityContextHolder.getUserKey());
        }
        List<JSONObject> namespaceJsonArray = null;
        JSONObject namespaceJsonObject = RancherResponseHandler.handleJsonObject(response, "获取K8S命名空间列表");
        if (namespaceJsonObject != null) {
            if (isNative && namespaceJsonObject.containsKey("items")) {
                namespaceJsonArray = namespaceJsonObject.getList("items", JSONObject.class);
            } else if (!isNative && namespaceJsonObject.containsKey("data")) {
                namespaceJsonArray = namespaceJsonObject.getList("data", JSONObject.class);
            }
        }
        if (namespaceJsonArray != null) {
            boolean finalIsNative = isNative;
            k8sNamespaceList = namespaceJsonArray
                    .stream()
                    .map(x -> K8sNamespace.jsonObjectToK8sNamespace(x, finalIsNative))
                    .filter(x -> StringUtils.isNotEmpty(x.getKey()))
                    .collect(Collectors.toList());
        }
        return k8sNamespaceList;
    }

    @Override
    public List<MetricCommonData> getMetricCommonDataList(JSONObject metricResJson) {
        List<MetricCommonData> metricCommonDataList = new ArrayList<>();
        if (metricResJson != null && metricResJson.containsKey("data")) {
            PrometheusResVo prometheusResVo = metricResJson.toJavaObject(PrometheusResVo.class);
            if (prometheusResVo != null && prometheusResVo.isSuccess()) {
                PrometheusResultVo prometheusResultVo = prometheusResVo.getData().getResult().get(0);
                if (prometheusResultVo.getValues() != null) {
                    metricCommonDataList = MetricCommonData.prometheusResultVoToMetric(prometheusResultVo.getValues());
                }
            }
        }
        return metricCommonDataList;
    }

    @Override
    public JSONArray getSentinelAppList() {
        JSONObject sentinelAppList = remoteGatewayService.getSentinelAppList(SecurityContextHolder.getUserKey());
        if (sentinelAppList != null && sentinelAppList.containsKey("success") && sentinelAppList.getBoolean("success")) {
            JSONArray sentinelAppListArray = sentinelAppList.getJSONArray("data");
            if (sentinelAppListArray != null && !sentinelAppList.getJSONArray("data").isEmpty()) {
                return sentinelAppListArray;
            }
        }
        return new JSONArray();
    }
}
