package cn.qg.qaplatform.utils;

import com.alibaba.fastjson.JSON;
import io.fabric8.kubernetes.api.model.Namespace;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.api.model.Service;
import io.fabric8.kubernetes.api.model.ServicePort;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Component
public class K8sService {

    private KubernetesClient kubernetesClient;

    public K8sService() {
        try {
            String configYAML = String.join("\n", readConfigFile("kube-config.yml"));
            Config config = Config.fromKubeconfig(configYAML);
            kubernetesClient = new DefaultKubernetesClient(config);
            String configCrt = String.join("\n", readConfigFile("tke-cluster-ca.crt"));
            config.setCaCertData(configCrt);
            log.info("k8s连接初始化成功！");
        } catch (Exception e) {
            log.info("k8s service 初始化失败！");
            e.printStackTrace();
        }
    }

    /**
     * 读取k8s配置文件
     * @param file 配置文件名
     * @return
     * @throws IOException
     */
    private static List<String> readConfigFile(String file) throws IOException {
        String str = "";
        ClassPathResource resource = new ClassPathResource(file);
        InputStream in = resource.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        List<String> result = new ArrayList<>();
        while ((str = br.readLine()) != null) {
            result.add(str);
        }
        return result;
    }

    /**
     * 获取环境的所有k8s变量
     * @param namespace 环境
     */
    public Map<String, Object> getListEnvVars(String namespace) {
        Map<String, Object> envMap = new TreeMap<>();
        List<Pod> podList = kubernetesClient.pods().inNamespace(namespace).list().getItems();
        List<Service> serviceList = kubernetesClient.services().inNamespace(namespace).list().getItems();
        // 遍历Pod列表
        for (Pod pod: podList) {
            if (!pod.getStatus().getPhase().equals("Failed")) {
                String serviceName = pod.getMetadata().getLabels().get("qcloud-app");
                serviceName = serviceName.replace("-", "_").toUpperCase();
                envMap.put(serviceName + "_SERVICE_HOST", pod.getStatus().getHostIP());
                // MYSQL需要额外加个参数
                if (serviceName.equals("MYSQL")) {
                    envMap.put("DB_SERVICE_HOST", pod.getStatus().getHostIP());
                }
            }
        }
        // 遍历Service列表
        for (Service service: serviceList) {
            String serviceName = service.getMetadata().getName().toUpperCase().replaceAll("-", "_");
            List<ServicePort> servicePortList = service.getSpec().getPorts();
            if (service.getMetadata().getLabels().get("type").equals("base")) {
                if (servicePortList.get(0).getPort() != null) {
                    envMap.put(serviceName + "_SERVICE_PORT", servicePortList.get(0).getNodePort());
                    // MYSQL需要额外加个参数
                    if (serviceName.equals("MYSQL")) {
                        envMap.put("DB_SERVICE_PORT", servicePortList.get(0).getNodePort());
                    }
                }
                for (ServicePort servicePort: servicePortList) {
                    envMap.put(serviceName + "_SERVICE_PORT_" + servicePort.getPort(), servicePort.getNodePort());
                    // MYSQL需要额外加个参数
                    if (serviceName.equals("MYSQL")) {
                        envMap.put("DB_SERVICE_PORT_" + servicePort.getPort(), servicePort.getNodePort());
                    }
                }
            } else {
                if (servicePortList.get(0).getNodePort() != null) {
                    envMap.put(serviceName + "_SERVICE_PORT", servicePortList.get(0).getNodePort());
                }
                for (ServicePort servicePort: servicePortList) {
                    if (service.getSpec().getType().equals("NodePort")) {
                        envMap.put(serviceName + "_SERVICE_PORT_" + servicePort.getPort(), servicePort.getNodePort());
                    } else if (service.getSpec().getType().equals("ClusterIP")) {
                        envMap.put(serviceName + "_SERVICE_PORT_" + servicePort.getName(), servicePort.getPort());
                    }
                }
            }
        }
        return envMap;
    }

    /**
     * 获取namespace列表
     * @return
     */
    public List<Map<String, String>> getNamespaceList(String env) {
            List<Map<String, String>> resultList = new ArrayList<>();
            List<Namespace> namespaceList = kubernetesClient.namespaces().list().getItems();
            for (Namespace namespace : namespaceList) {
                if (namespace.getMetadata().getAnnotations() != null && env.equals("all")) {
                    String name = namespace.getMetadata().getName();
                    // 获取Service
                    Service service = kubernetesClient.services().inNamespace(name).withName("mysql").get();
                    // 获取Pod
                    Map<String, String> labels = new HashMap<>();
                    labels.put("qcloud-app", "mysql");
                    labels.put("type", "base");
                    List<Pod> podList = kubernetesClient.pods().inNamespace(name).withLabels(labels).list().getItems();
                    Integer port = null;
                    String host = null;
                    if (service != null) {
                        port = service.getSpec().getPorts().get(0).getNodePort();
                    }
                    if (podList.size() == 1) {
                        host = podList.get(0).getStatus().getHostIP();
                    }
                    if (podList.size() >= 2) {
                        for (Pod pod: podList) {
                            if (pod.getStatus().getHostIP() != null) {
                                host = pod.getStatus().getHostIP();
                                break;
                            }
                        }
                    }
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
                    df.setTimeZone(TimeZone.getTimeZone("UTC"));
                    SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Map<String, String> map = new HashMap<>();
                    map.put("name", name);
                    map.put("description", namespace.getMetadata().getAnnotations().get("description"));
                    map.put("owner", namespace.getMetadata().getAnnotations().get("owner"));
                    map.put("status", namespace.getStatus().getPhase());
                    map.put("mysqlHost", host);
                    map.put("mysqlPort", String.valueOf(port));
                    try {
                        map.put("createdAt", df2.format(df.parse(namespace.getMetadata().getCreationTimestamp())));
                    } catch (Exception e) {
                        log.info("时间解析异常！");
                        e.printStackTrace();
                        map.put("createdAt", namespace.getMetadata().getCreationTimestamp());
                    }
                    resultList.add(map);
                } else if (namespace.getMetadata().getAnnotations() != null && namespace.getMetadata().getAnnotations().get("description").equals(env)) {
                    String name = namespace.getMetadata().getName();
                    // 获取Service
                    Service service = kubernetesClient.services().inNamespace(name).withName("mysql").get();
                    // 获取Pod
                    Map<String, String> labels = new HashMap<>();
                    labels.put("qcloud-app", "mysql");
                    labels.put("type", "base");
                    List<Pod> podList = kubernetesClient.pods().inNamespace(name).withLabels(labels).list().getItems();
                    Integer port = null;
                    String host = null;
                    if (service != null) {
                        port = service.getSpec().getPorts().get(0).getNodePort();
                    }
                    if (podList.size() == 1) {
                        host = podList.get(0).getStatus().getHostIP();
                    }
                    if (podList.size() >= 2) {
                        for (Pod pod: podList) {
                            if (pod.getStatus().getHostIP() != null) {
                                host = pod.getStatus().getHostIP();
                                break;
                            }
                        }
                    }
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
                    df.setTimeZone(TimeZone.getTimeZone("UTC"));
                    SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Map<String, String> map = new HashMap<>();
                    map.put("name", name);
                    map.put("description", namespace.getMetadata().getAnnotations().get("description"));
                    map.put("owner", namespace.getMetadata().getAnnotations().get("owner"));
                    map.put("status", namespace.getStatus().getPhase());
                    map.put("mysqlHost", host);
                    map.put("mysqlPort", String.valueOf(port));
                    try {
                        map.put("createdAt", df2.format(df.parse(namespace.getMetadata().getCreationTimestamp())));
                    } catch (Exception e) {
                        log.info("时间解析异常！");
                        e.printStackTrace();
                        map.put("createdAt", namespace.getMetadata().getCreationTimestamp());
                    }
                    resultList.add(map);
                }
            }
            return resultList;
    }
}
