package cd.casic.module.execute.docker;

import cd.casic.module.execute.docker.dao.DockerEndpointDao;
import cd.casic.module.execute.docker.dataobject.convert.DockerEndpointConvert;
import cd.casic.module.execute.docker.dataobject.model.DockerEndpoint;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.core.DockerClientBuilder;
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
import jakarta.annotation.Resource;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

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

import static java.lang.String.format;

/**
 * @description: docker客户端工厂
 * @author: mianbin
 * @date: 2025/5/26 10:39
 * @version: 1.0
 */
@Slf4j
@Component
public class DockerClientFactory implements CommandLineRunner {

    @Resource(type = DockerEndpointDao.class)
    private DockerEndpointDao dockerEndpointDao;
    @Getter
    private final Map<String, DockerClient> clientGroup = new ConcurrentHashMap<>();

    @Override
    public void run(String... args) throws Exception {
        /*如果在ops里面之前添加过，数据库之前有，那么启动就加载，如果是手动添加的，后面要注意控制*/
        dockerEndpointDao.selectList().stream()
                .map(DockerEndpointConvert.INSTANCE::convert)
                .forEach(endpoint -> {
                    ApacheDockerHttpClient httpClient = createHttpClient(endpoint);
                    if (httpClient != null) {
                        DockerClient client = DockerClientBuilder.getInstance().withDockerHttpClient(httpClient).build();
                        clientGroup.put(endpoint.getId(), client);
                    }
                });
    }

    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;
        }
    }

    public DockerClient getdockerClient(String id) {
        return clientGroup.get(id);
    }
}
