use anyhow::Result;
use clap::Args as ClapArgs;

/// Kill the running server, rebuild (if --build), restart it on the
/// same port + chip library, and reload the pup browser window.
/// One command replaces the 5-step restart cycle that kept tripping
/// up the AI: kill → build → start → confirm alive → reload browser.
#[derive(ClapArgs)]
pub struct Args {
    /// Port (default 8872)
    #[arg(long, default_value_t = 8872)]
    port: u16,

    /// Rebuild before restarting (`cargo build --release` + touch mod.rs)
    #[arg(long)]
    build: bool,

    /// Pup session ID to reload after restart
    #[arg(long, default_value = "chipsmith")]
    session: String,

    /// Max seconds to wait for the server to become healthy
    #[arg(long, default_value_t = 30)]
    timeout: u32,
}

pub fn run(args: Args) -> Result<()> {
    let port = args.port;

    // 1. Kill the running server
    eprint!("stopping port {}... ", port);
    let _ = ureq::post(&format!("http://127.0.0.1:{port}/shutdown"))
        .call();
    std::thread::sleep(std::time::Duration::from_secs(1));
    eprintln!("done");

    // 2. Optional rebuild
    if args.build {
        eprint!("building... ");
        // Touch mod.rs to force include_bytes! re-embed of changed assets
        let _ = std::fs::File::open("src/server/mod.rs")
            .and_then(|f| f.set_modified(std::time::SystemTime::now()).map(|_| f));
        let status = std::process::Command::new("cargo")
            .args(["build", "--release"])
            .status()?;
        if !status.success() {
            anyhow::bail!("cargo build failed");
        }
        eprintln!("done");
    }

    // 3. Read the last-known library dir from the server state (saved
    //    at /tmp/adom-chipsmith-last-library). Fall back to env var.
    let state_file = std::path::PathBuf::from("/tmp/adom-chipsmith-last-library");
    let lib_dir = if state_file.exists() {
        std::fs::read_to_string(&state_file)?.trim().to_string()
    } else if let Ok(d) = std::env::var("CHIPSMITH_LIBRARY") {
        d
    } else {
        anyhow::bail!("no last-known library dir — pass CHIPSMITH_LIBRARY env or run view-library first");
    };

    // 4. Start the server in background
    eprint!("starting on port {} with {}... ", port, lib_dir);
    let exe = std::env::current_exe()?;
    std::process::Command::new(&exe)
        .args(["view-library", "--no-open", "--port", &port.to_string(), &lib_dir])
        .stdin(std::process::Stdio::null())
        .stdout(std::process::Stdio::null())
        .stderr(std::process::Stdio::null())
        .spawn()?;

    // 5. Wait for healthy
    let deadline = std::time::Instant::now() + std::time::Duration::from_secs(args.timeout as u64);
    let url = format!("http://127.0.0.1:{port}/api/paths");
    loop {
        if std::time::Instant::now() > deadline {
            anyhow::bail!("server did not become healthy within {}s", args.timeout);
        }
        std::thread::sleep(std::time::Duration::from_millis(500));
        if ureq::get(&url).call().is_ok() {
            break;
        }
    }
    super::ok(format!("server alive on port {port}"));

    // 6. Reload the pup browser window
    let reload_result = std::process::Command::new("adom-desktop")
        .args(["browser_reload", &format!("{{\"sessionId\":\"{}\"}}", args.session)])
        .output();
    match reload_result {
        Ok(o) if o.status.success() => {
            super::ok(format!("browser reloaded (session: {})", args.session));
        }
        _ => {
            super::hint(format!("browser reload failed — manually reload session '{}'", args.session));
        }
    }

    // 7. Wait for chipsmith JS to init (poll eval)
    let eval_url = format!("http://127.0.0.1:{port}/eval");
    let deadline2 = std::time::Instant::now() + std::time::Duration::from_secs(15);
    loop {
        if std::time::Instant::now() > deadline2 { break; }
        std::thread::sleep(std::time::Duration::from_secs(1));
        // Can't easily check the browser JS from here — the server's
        // /eval endpoint doesn't exist. Just wait a reasonable time.
    }

    super::ok("restart complete — server + browser reloaded");
    Ok(())
}