package cn.reghao.devops.mgr.devops;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import cn.reghao.devops.common.docker.DockerImpl;
import cn.reghao.devops.common.docker.model.Config;
import cn.reghao.devops.common.docker.model.Volumes;
import cn.reghao.jutil.jdk.converter.IpAddressConverter;
import cn.reghao.jutil.jdk.serializer.JsonConverter;
import com.github.dockerjava.api.command.InspectContainerResponse;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import oshi.SystemInfo;
import oshi.software.os.InternetProtocolStats;
import oshi.software.os.OperatingSystem;

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

/**
 * @author reghao
 * @date 2022-05-07 09:32:40
 */
@Slf4j
public class DockerTest {
    void setLogLevel() {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        Logger rootLogger = loggerContext.getLogger("ROOT");
        rootLogger.setLevel(Level.INFO);
    }

    List<ListenProcess> getListenProcesses() {
        IpAddressConverter ipAddressConverter = new IpAddressConverter();
        SystemInfo si = new SystemInfo();
        OperatingSystem os = si.getOperatingSystem();

        List<SysProcess> sysProcessList = new ArrayList<>();
        os.getProcesses().forEach(osProcess -> {
            int pid = osProcess.getProcessID();
            String name = osProcess.getName();
            int ppid = osProcess.getParentProcessID();
            sysProcessList.add(new SysProcess(pid, name, ppid));
        });

        String state = InternetProtocolStats.TcpState.LISTEN.name();
        List<ListenProcess> list = new ArrayList<>();
        os.getInternetProtocolStats().getConnections().forEach(ipConnection -> {
            if (!ipConnection.getState().name().equals(state)) {
                return;
            }

            String type = ipConnection.getType();
            int pid = ipConnection.getowningProcessId();
            byte[] localAddress = ipConnection.getLocalAddress();
            int localPort = ipConnection.getLocalPort();
            byte[] remoteAddress = ipConnection.getForeignAddress();
            int remotePort = ipConnection.getForeignPort();
            System.out.printf("%s %s %s %s\n", pid, type, state, localPort);
            list.add(new ListenProcess(pid, type, localPort));
        });

        Map<Integer, List<ListenProcess>> groupMap = list.stream().collect(Collectors.groupingBy(ListenProcess::getPid));
        os.getProcesses().forEach(osProcess -> {
            int pid = osProcess.getProcessID();
            List<ListenProcess> list1 = groupMap.get(pid);
            if (list1 != null && !list1.isEmpty()) {
                String name = osProcess.getName();
                list1.get(0).setName(name);
            }
        });

        return list;
    }

    @Test
    public void dockerListTest() {
        setLogLevel();

        List<ListenProcess> listenProcessList = getListenProcesses();
        DockerImpl docker = new DockerImpl();
        List<InspectContainerResponse> list = docker.psAll();
        for (InspectContainerResponse response : list) {
            String imageId = response.getImageId();
            Boolean running = response.getState().getRunning();
            if (running != null && running) {
                Integer pid = response.getState().getPid();
                if (pid == null) {
                    pid = -1;
                }

                String containerId = response.getId();
                String appId = response.getName().replace("/", "");
                System.out.printf("%s: %s -> %s\n", pid, containerId, appId);
            }
        }
    }

    @Test
    public void dockerBuildTest() throws Exception {
        setLogLevel();
        DockerImpl docker = new DockerImpl();
        /*String repoTag = "file:12345678";
        String compileHome = "/home/reghao/code/aha/tnb/file/file-service";
        docker.build(repoTag, compileHome);*/

        String image = "node:16.20.2-buster-slim";
        String sourceCodeDir = "/home/reghao/Downloads/0/tnbapp";
        sourceCodeDir = "/home/reghao/Downloads/0/iquizoo.admin/";
        String nodeModulesDir = "/home/reghao/Downloads/0/node_modules";
        String buildCmd = "npm run build";
        String buildCmd1 = "npm i && npm run build";
        String buildCmd2 = "npm run test";
        String buildCmd3 = "cd /app && npm --registry http://registry.npm.taobao.org i && npm run uat";
        String buildCmd4 = "npm --registry http://registry.npm.taobao.org i";

        Config config = new Config(image);
        config.setVolumes(new Volumes());
        config.setCmd(List.of("sh", "-c", buildCmd3));

        Map<String, String> map = config.getVolumes().getMap();
        map.put("/node_modules", nodeModulesDir);
        map.put("/app", sourceCodeDir);

        long start = 0;
        start = System.currentTimeMillis();
        docker.runAndRm(config);
        log.info("cost {} ms", System.currentTimeMillis()-start);

        /*config.setCmd(List.of("sh", "-c", "cd /front && " + buildCmd1));
        start = System.currentTimeMillis();
        docker.runAndRm(config);
        log.info("cost {} ms", System.currentTimeMillis()-start);*/
    }

    /**
     * 解析 docker 容器启动参数
     *
     * @param
     * @return
     * @date 2025-07-04 15:51:09
     */
    @Test
    public void parseContainerArgsTest() {
        String image = "node:16.20.2-buster-slim";
        Config config = new Config(image);
        config.setVolumes(new Volumes());
        config.getHostConfig().setInit(true);

        String json = JsonConverter.objectToJson(config);
        System.out.println(json);

        String json1 = "{ \"Env\":[\"ASPNETCORE_ENVIRONMENT=Production\", \"ASPNETCORE_URLS=http://172.16.45.67:8015;https://172.16.45.67:8115\"], \"HostConfig\":{\"Init\":true}}";
        Config config1 = JsonConverter.jsonToObject(json1, Config.class);
        System.out.println();
    }

    @Setter
    @Getter
    static class ListenProcess {
        private int pid;
        private String name;
        private String type;
        private int port;

        public ListenProcess(int pid, String type, int port) {
            this.pid = pid;
            this.type = type;
            this.port = port;
        }
    }

    @AllArgsConstructor
    @Getter
    static class SysProcess {
        private int pid;
        private String name;
        private int ppid;
    }
}
