//! Up command - starts all SEA services

use anyhow::{Context, Result};
use colored::Colorize;
use indicatif::{ProgressBar, ProgressStyle};
use std::path::Path;
use std::process::Command;
use std::time::Duration;

/// Run the up command
pub async fn run(services: Option<Vec<String>>, _detach: bool, dry_run: bool) -> Result<()> {
    println!("{}", "🚀 Starting SEA services...".bold());
    println!();

    let project_root = find_project_root()?;
    let librechat_dir = project_root.join("deploy/librechat");

    if !librechat_dir.exists() {
        anyhow::bail!(
            "LibreChat directory not found at {}. Run 'sea-forge setup' first.",
            librechat_dir.display()
        );
    }

    // Start skeleton services first
    println!("{}", "1. Starting skeleton services (Oxigraph, OPA)...".dimmed());
    if dry_run {
        println!("  {} Would run: just skeleton-up", "[DRY-RUN]".cyan());
    } else {
        run_just_command(&project_root, &["skeleton-up"])?;
    }

    // Start LibreChat stack
    println!();
    println!("{}", "2. Starting LibreChat stack...".dimmed());

    let spinner = ProgressBar::new_spinner();
    spinner.set_style(
        ProgressStyle::default_spinner()
            .template("{spinner:.cyan} {msg}")
            .unwrap(),
    );
    spinner.enable_steady_tick(Duration::from_millis(100));

    if dry_run {
        println!("  {} Would run: docker compose up -d", "[DRY-RUN]".cyan());
    } else {
        spinner.set_message("Pulling images...");

        let mut cmd = Command::new("docker");
        cmd.args(["compose", "up", "-d"]);
        cmd.current_dir(&librechat_dir);

        if let Some(ref svcs) = services {
            for svc in svcs {
                cmd.arg(svc);
            }
        }

        let output = cmd.output().context("Failed to run docker compose")?;

        if !output.status.success() {
            spinner.finish_with_message("Failed!".red().to_string());
            let stderr = String::from_utf8_lossy(&output.stderr);
            anyhow::bail!("Docker compose failed: {}", stderr);
        }

        spinner.finish_with_message("Started!".green().to_string());
    }

    // Wait for health
    if !dry_run {
        println!();
        println!("{}", "3. Waiting for services to be healthy...".dimmed());
        tokio::time::sleep(Duration::from_secs(5)).await;
    }

    // Print access info
    println!();
    println!("{}", "═══════════════════════════════════════════".cyan());
    println!("{}", "  Services Running".bold());
    println!("{}", "═══════════════════════════════════════════".cyan());
    println!();
    println!("  LibreChat:  {}", "http://localhost:3080".cyan().underline());
    println!("  SEA API:    {}", "http://localhost:8080".cyan().underline());
    println!("  API Docs:   {}", "http://localhost:8080/docs".cyan().underline());
    println!("  Oxigraph:   {}", "http://localhost:7878".dimmed());
    println!();
    println!("Commands:");
    println!("  {} Check service health", "sea-forge status".cyan());
    println!("  {} View logs", "sea-forge logs".cyan());
    println!("  {} Stop services", "sea-forge down".cyan());

    Ok(())
}

fn find_project_root() -> Result<std::path::PathBuf> {
    let current = std::env::current_dir()?;
    let mut path = current.as_path();

    loop {
        if path.join("justfile").exists() && path.join("Cargo.toml").exists() {
            return Ok(path.to_path_buf());
        }
        path = path.parent().context("Could not find SEA project root")?;
    }
}

fn run_just_command(cwd: &Path, args: &[&str]) -> Result<()> {
    let output = Command::new("just")
        .args(args)
        .current_dir(cwd)
        .output()
        .context("Failed to run just command")?;

    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        anyhow::bail!("just {} failed: {}", args.join(" "), stderr);
    }

    Ok(())
}
