package cd.casic.module.execute;

import cd.casic.module.execute.docker.callback.CommandExecCallback;
import cd.casic.module.execute.docker.dataobject.model.DockerEndpoint;
import cd.casic.module.execute.docker.dataobject.model.RunNewContainer;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.async.ResultCallback;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.command.ExecCreateCmdResponse;
import com.github.dockerjava.api.command.InspectContainerResponse;
import com.github.dockerjava.api.command.TopContainerResponse;
import com.github.dockerjava.api.exception.NotFoundException;
import com.github.dockerjava.api.model.*;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static java.lang.String.format;
import static java.lang.Thread.sleep;

/**
 * @description: TODO
 * @author: mianbin
 * @date: 2025/5/26 20:11
 * @version: 1.0
 */
@Slf4j
public class ContainerServiceTest {

    private final Map<String, DockerClient> clientGroup = new ConcurrentHashMap<>();

    private ApacheDockerHttpClient createHttpClient(DockerEndpoint endpoint) {
        try {
            URI dockerHost;
            if (endpoint.getType() == DockerEndpoint.DockerEndpointTypeEnum.LOCAL) {
                // 使用本地挂载
                dockerHost = new URI("unix:///var/run/docker.sock");
            } else if (endpoint.getType() == DockerEndpoint.DockerEndpointTypeEnum.REMOTE) {
                // 远程挂载
                dockerHost = new URI(format("tcp://%s:%s", endpoint.getHost(), endpoint.getPort()));
            } else {
                log.error("Unsupported Docker endpoint type: {}", endpoint.getType());
                return null;
            }
            return new ApacheDockerHttpClient.Builder()
                    .dockerHost(dockerHost)
                    .build();
        } catch (URISyntaxException e) {
            log.error("Failed to create URI for Docker endpoint {}: {}", endpoint.getId(), e.getMessage(), e);
            return null;
        }
    }

    @BeforeEach
    public void setUp() {
        DockerEndpoint endpoint = new DockerEndpoint();
        endpoint.setId("158");
        endpoint.setType(DockerEndpoint.DockerEndpointTypeEnum.REMOTE);
        endpoint.setHost("175.6.27.158");
        endpoint.setPort(22375);
        endpoint.setName("test");
        ApacheDockerHttpClient httpClient = createHttpClient(endpoint);
        DockerClient dockerClient = DockerClientBuilder.getInstance().withDockerHttpClient(httpClient).build();
        clientGroup.put(endpoint.getId(), dockerClient);
    }

    @Test
    public void list() {
        DockerClient dockerClient = clientGroup.get("158");
        List<Container> exec =
                dockerClient.listContainersCmd().withShowAll(true).exec();
        System.out.println(exec.size());
    }

    /**
     * 能启动，但是参数都没生效的样子
     *
     */
    @Test
    public void start() {
        String imagesId = "be69f2940aaf";
        DockerClient dockerClient = clientGroup.get("158");
        // 创建 RunNewContainer 对象并设置属性
        RunNewContainer runNewContainer = new RunNewContainer();
        runNewContainer.setImageId(imagesId);
        runNewContainer.setAlias("nginx");
        runNewContainer.setDns(Arrays.asList("8.8.8.8", "8.8.4.4"));
        runNewContainer.setContainerName("nginx_test_api");
        runNewContainer.setHostname("nginx.testapi.host.name");
        Map<String, String> key1 = Map.of("KEY1", "VALUE1", "KEY2", "VALUE2");
        runNewContainer.setEnvGroup(key1);
        runNewContainer.setNetworkMode("nginx_test_net_work");

        HostConfig hostConfig = HostConfig.newHostConfig();
        hostConfig.withBinds(Bind.parse("/host:/container:ro"))
                .withPortBindings(PortBinding.parse("12:44"))
                .withDns(runNewContainer.getDns()).withNetworkMode(runNewContainer.getNetworkMode());
        final CreateContainerResponse response = dockerClient
                .createContainerCmd(runNewContainer.getImageId())
                .withAliases(runNewContainer.getAlias())
                .withHostConfig(hostConfig)
                .withEnv(runNewContainer.findEnvList())
                .withName(runNewContainer.getContainerName())
                .withHostName(runNewContainer.getHostname()).exec();
    }

    @Test
    public void stop() {
        String containerId = "d7d747696f43";
        DockerClient dockerClient = clientGroup.get("158");
        dockerClient.stopContainerCmd(containerId).exec();
        log.info("停止容器,containerId={}", containerId);
    }

    /*没有成功，不知道为啥，暂停不研究了*/
    @Test
    public void pause() {
        String containerId = "c1ffcaf2ff8d";
        DockerClient dockerClient = clientGroup.get("158");
        dockerClient.pauseContainerCmd(containerId).exec();
        log.info("停止容器,containerId={}", containerId);
    }

    @Test
    public void unpause() {
        String containerId = "c1ffcaf2ff8d";
        DockerClient dockerClient = clientGroup.get("158");
        try {
            dockerClient.unpauseContainerCmd(containerId).exec();
            log.info("重启容器,containerId={}", containerId);
        } catch (NotFoundException e) {
            log.info("重启容器失败,containerId={}，异常", containerId, e.getMessage());
        }
    }

    @Test
    public void rename() {
        String containerId = "d7d747696f43";
        String newName = "nginx";
        DockerClient dockerClient = clientGroup.get("158");
        dockerClient.renameContainerCmd(containerId).withName(newName).exec();
        log.info("重命名容器:[{}]为[{}]", containerId, newName);
    }

    @Test
    public void top() {
        String containerId = "d7d747696f43";
        String newName = "nginx";
        DockerClient dockerClient = clientGroup.get("158");
        TopContainerResponse aux = dockerClient.topContainerCmd(containerId).withPsArgs("aux").exec();
        log.info("", aux.getTitles());
    }

    @Test
    public void inspect() {
        String containerId = "d7d747696f43";
        DockerClient dockerClient = clientGroup.get("158");
        final InspectContainerResponse response =
                dockerClient.inspectContainerCmd(containerId).withSize(Boolean.TRUE).exec();
        System.out.println(response);
    }

    @Test
    public void remove() {
        String containerId = "d7d747696f43";
        DockerClient dockerClient = clientGroup.get("158");
        dockerClient.removeContainerCmd(containerId)
                /*删除默认强制删除，并且挂载内容一并删除*/
                .withForce(true)
                .withRemoveVolumes(true).exec();
        log.info("移除容器,containerId={}", containerId);
    }

    /*这个测试，用处不大*/
    @Test
    public void setLog() throws InterruptedException {
        String containerId = "d7d747696f43";
        DockerClient dockerClient = clientGroup.get("158");
        /*创建命令*/
        String execId = dockerClient.execCreateCmd(containerId)
                .withCmd("ls")
                .withAttachStdin(true)
                .withAttachStdout(true)
                .withAttachStderr(true)
                .withTty(true)
                .exec().getId();
        // 执行命令并记录日志
        ResultCallback<Frame> callback = new CommandExecCallback(containerId);
        /*这个是异步的方法*/
        dockerClient.execStartCmd(execId)
                .withTty(true)
                .exec(callback);
        sleep(1000);
    }

    @Test
    public void execCmd() throws InterruptedException {
        String containerId = "c1ffcaf2ff8d22ae9f1d9a91d0714d086ec2812809aec1558c9512b04168c125";
        DockerClient dockerClient = clientGroup.get("158");
        ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId)
                .withAttachStdout(true)
                .withAttachStderr(true)
                .withCmd("ls", "-l")
                .exec();
        dockerClient
                .execStartCmd(execCreateCmdResponse.getId())
                .exec(new CommandExecCallback(containerId))
                .awaitCompletion();
    }

}
