package cn.reghao.bnt.common.agent.app.iface.impl;

import cn.reghao.bnt.common.docker.Docker;
import cn.reghao.bnt.common.docker.DockerImpl;
import cn.reghao.bnt.common.docker.model.Config;
import cn.reghao.bnt.common.docker.model.DockerAuth;
import cn.reghao.bnt.common.docker.model.HostConfig;
import cn.reghao.bnt.common.machine.Machine;
import cn.reghao.bnt.common.msg.constant.NodeStatus;
import cn.reghao.bnt.common.msg.event.EvtAppDeploy;
import cn.reghao.bnt.common.msg.event.EvtAppStatResult;
import cn.reghao.jutil.jdk.web.result.NotAvailable;
import cn.reghao.jutil.jdk.converter.DateTimeConverter;
import cn.reghao.jutil.jdk.serializer.JsonConverter;
import com.github.dockerjava.api.command.InspectContainerResponse;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2023-03-06 15:26:22
 */
public class DockerApp {
    private Map<String, Docker> map = new HashMap<>();

    public DockerApp(Docker docker) {
        this.map.put("noAuth", docker);
    }

    public EvtAppStatResult deploy(EvtAppDeploy deployParam) throws Exception {
        String appId = deployParam.getAppId();
        String packagePath = deployParam.getPackagePath();
        Config containerConfig = JsonConverter.jsonToObject(deployParam.getStartScript(), Config.class);
        if (containerConfig == null) {
            containerConfig = new Config(packagePath);
        } else {
            containerConfig.setImage(packagePath);
            if (containerConfig.getHostConfig() == null) {
                containerConfig.setHostConfig(new HostConfig());
            }
        }

        Docker docker;
        DockerAuth dockerAuth = deployParam.getDockerAuth();
        if (dockerAuth != null) {
            String registryUrl = dockerAuth.getRegistryUrl();
            docker = map.get(registryUrl);
            if (docker == null) {
                // TODO DockerAuth 修改后 map 中的 Docker 实例无效
                docker = new DockerImpl(dockerAuth);
                map.put(registryUrl, docker);
            }
        } else {
            docker = map.get("noAuth");
        }
        docker.pull(packagePath);
        InspectContainerResponse containerInfo = docker.createAndRun(appId, containerConfig);
        return getStat(appId, containerInfo);
    }

    public EvtAppStatResult start(String appId) throws Exception {
        Docker docker = map.get("noAuth");
        InspectContainerResponse containerInfo = docker.start(appId);
        return getStat(appId, containerInfo);
    }

    public EvtAppStatResult stop(String appId) throws Exception {
        Docker docker = map.get("noAuth");
        InspectContainerResponse containerInfo = docker.stop(appId);
        return getStat(appId, containerInfo);
    }

    public EvtAppStatResult restart(String appId) throws Exception {
        Docker docker = map.get("noAuth");
        InspectContainerResponse containerInfo = docker.restart(appId);
        return getStat(appId, containerInfo);
    }

    public EvtAppStatResult stat(String appId) throws Exception {
        Docker docker = map.get("noAuth");
        InspectContainerResponse containerInfo = docker.inspectContainer(appId);
        return getStat(appId, containerInfo);
    }

    public List<EvtAppStatResult> stat() throws Exception {
        Docker docker = map.get("noAuth");
        List<InspectContainerResponse> list = docker.psAll();
        return list.stream().map(response -> {
            String containerName = response.getName();
            String appId = containerName.replace("/", "");
            return getStat(appId, response);
        }).collect(Collectors.toList());
    }

    private EvtAppStatResult getStat(String appId, InspectContainerResponse containerInfo) {
        EvtAppStatResult appStatResult = new EvtAppStatResult(appId, Machine.ID);
        String image = containerInfo.getConfig().getImage();
        if (image != null && image.contains(":")) {
            appStatResult.setCommitId(image.split(":")[1]);
        } else {
            appStatResult.setCommitId(NotAvailable.na.getDesc());
        }

        InspectContainerResponse.ContainerState state = containerInfo.getState();
        if (state == null || Boolean.FALSE.equals(state.getRunning())) {
            //appStatResult.setStatus(NodeStatus.Offline.name());
            appStatResult.setStartTime(null);
            appStatResult.setPid(-1);
        } else {
            String startedAt = state.getStartedAt();
            //appStatResult.setStatus(NodeStatus.Online.name());
            appStatResult.setRunning(true);
            appStatResult.setStartTime(DateTimeConverter.localDateTime(startedAt));
            appStatResult.setPid(state.getPidLong().intValue());
        }

        return appStatResult;
    }
}
