package cd.casic.module.execute.docker.service.impl;

import cd.casic.module.execute.docker.DockerClientFactory;
import cd.casic.module.execute.docker.service.IImageService;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.InspectImageResponse;
import com.github.dockerjava.api.command.SaveImageCmd;
import com.github.dockerjava.api.exception.NotFoundException;
import com.github.dockerjava.api.model.Image;
import com.github.dockerjava.api.model.PruneType;
import jakarta.annotation.Nonnull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

/**
 * @description: 镜像的服务类
 * @author: mianbin
 * @date: 2025/5/26 15:06
 * @version: 1.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ImageService implements IImageService {

    private final DockerClientFactory dockerClientFactory;

    @Override
    public List<Image> list(@Nonnull String clientId) {
        DockerClient dockerClient = dockerClientFactory.getdockerClient(clientId);
        return dockerClient.listImagesCmd().exec();
    }

    @Override
    public InspectImageResponse inspect(@Nonnull String clientId, @Nonnull String imageId) {
        DockerClient dockerClient = dockerClientFactory.getdockerClient(clientId);
        return dockerClient.inspectImageCmd(imageId).exec();
    }

    @Override
    public void tag(@Nonnull String clientId, String imageId, String newTag) {
        InspectImageResponse inspect = inspect(clientId, imageId);
        if (inspect == null) {
            throw new RuntimeException("操作失败，镜像不存在");
        }
        DockerClient dockerClient = dockerClientFactory.getdockerClient(clientId);
        dockerClient.tagImageCmd(imageId, inspect.getRepoTags().get(0), newTag).exec();
    }

    @Override
    public void remove(@Nonnull String clientId, String imageId, Boolean force) {
        DockerClient dockerClient = dockerClientFactory.getdockerClient(clientId);
        dockerClient.removeImageCmd(imageId).withForce(force).exec();
    }

    @Override
    public void export(@Nonnull String clientId, String imageId) {
        DockerClient dockerClient = dockerClientFactory.getdockerClient(clientId);
        /*这个api我要查下，不生效也无所，感觉场景很少*/
    }

    /*经过测试，只有local 模式下面生效*/
    @Override
    public void importByFile(@Nonnull String clientId, String file) {
        DockerClient dockerClient = dockerClientFactory.getdockerClient(clientId);
        /*test 测试下，这个不知道生效不*/
        dockerClient.loadImageCmd(FileUtil.getInputStream(file)).exec();
    }

    /*经过测试，只有local 模式下面生效*/
    @Override
    public void importByTar(@Nonnull String clientId, String file) {
        DockerClient dockerClient = dockerClientFactory.getdockerClient(clientId);
        /*test 测试下，这个不知道生效不*/
        dockerClient.loadImageCmd(FileUtil.getInputStream(file)).exec();
    }

    @Override
    public boolean exist(@Nonnull String clientId, String imageId) {
        DockerClient dockerClient = dockerClientFactory.getdockerClient(clientId);
        try {
            final InspectImageResponse inspectImage = dockerClient.inspectImageCmd(imageId).exec();
            return inspectImage != null;
        } catch (NotFoundException e) {
            return false;
        }
    }

    @Override
    public void pruneImage(String clientId) {
        DockerClient dockerClient = dockerClientFactory.getdockerClient(clientId);
        dockerClient.pruneCmd(PruneType.IMAGES).exec();
    }

    @Override
    public Boolean save(@Nonnull String clientId, String imageId, String outputPath) {
        DockerClient dockerClient = dockerClientFactory.getdockerClient(clientId);
        /*imageid 如 nginx:latest */
        try (OutputStream fos = new FileOutputStream(outputPath);
             SaveImageCmd saveImageCmd = dockerClient.saveImageCmd(imageId)) {
            // 执行命令并将输出写入文件流
            InputStream exec = saveImageCmd.exec();
            IoUtil.copy(exec, fos);
            log.info("镜像已成功保存到: " + outputPath);
            return Boolean.TRUE;
        } catch (IOException e) {
            log.error("保存镜像时发生 IO 错误: " + e.getMessage());
            return Boolean.FALSE;
        }
    }

    @Override
    public Boolean pushImage(@NotNull String clientId, String imageId) {
        DockerClient dockerClient = dockerClientFactory.getdockerClient(clientId);
        try {
            dockerClient.pushImageCmd(imageId).exec(null);
        } catch (Exception e) {
            log.error("推送镜像失败: " + e.getMessage());
            return false;
        }
        return true;
    }
}
