package com.cameleer.server.app.runtime;

import com.cameleer.server.app.search.ClickHouseLogStore;
import com.cameleer.server.app.storage.PostgresDeploymentRepository;
import com.cameleer.server.core.runtime.DeploymentRepository;
import com.cameleer.server.core.runtime.RuntimeOrchestrator;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientImpl;
import com.github.dockerjava.zerodep.ZerodepDockerHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.nio.file.Files;
import java.nio.file.Path;

@Configuration
public class RuntimeOrchestratorAutoConfig {

    private static final Logger log = LoggerFactory.getLogger(RuntimeOrchestratorAutoConfig.class);

    @Bean
    public DockerClient dockerClient() {
        if (!Files.exists(Path.of("/var/run/docker.sock"))) {
            return null;
        }
        var config = DefaultDockerClientConfig.createDefaultConfigBuilder()
                .withDockerHost("unix:///var/run/docker.sock")
                .build();
        var httpClient = new ZerodepDockerHttpClient.Builder()
                .dockerHost(config.getDockerHost())
                .build();
        DockerClient client = DockerClientImpl.getInstance(config, httpClient);
        log.info("Docker client initialized, host: {}", config.getDockerHost());
        return client;
    }

    @Bean
    public RuntimeOrchestrator runtimeOrchestrator(
            @Autowired(required = false) DockerClient dockerClient,
            @Autowired(required = false) ContainerLogForwarder logForwarder,
            @Value("${cameleer.server.runtime.dockerruntime:}") String dockerRuntimeOverride) {
        if (dockerClient != null) {
            log.info("Docker socket detected - enabling Docker runtime orchestrator");
            DockerRuntimeOrchestrator orchestrator =
                    new DockerRuntimeOrchestrator(dockerClient, dockerRuntimeOverride);
            if (logForwarder != null) {
                orchestrator.setLogForwarder(logForwarder);
            }
            return orchestrator;
        }
        log.info("No Docker socket or K8s detected - runtime management disabled (observability-only mode)");
        return new DisabledRuntimeOrchestrator();
    }

    @Bean
    public DockerNetworkManager dockerNetworkManager(
            @Autowired(required = false) DockerClient dockerClient) {
        if (dockerClient != null) {
            return new DockerNetworkManager(dockerClient);
        }
        return null;
    }

    @Bean
    public DockerEventMonitor dockerEventMonitor(RuntimeOrchestrator orchestrator,
                                                  @Autowired(required = false) DockerClient dockerClient,
                                                  DeploymentRepository deploymentRepository) {
        if (orchestrator instanceof DockerRuntimeOrchestrator docker && dockerClient != null) {
            return new DockerEventMonitor(docker, (PostgresDeploymentRepository) deploymentRepository);
        }
        return null;
    }

    @Bean
    public ContainerLogForwarder containerLogForwarder(
            @Autowired(required = false) DockerClient dockerClient,
            ClickHouseLogStore logStore) {
        if (dockerClient != null) {
            return new ContainerLogForwarder(dockerClient, logStore);
        }
        return null;
    }
}
