/// nf — Night Fury CLI
///
/// Interactive REPL for browser automation. Supports both interactive use
/// and scripted/piped input for agent workflows.
///
/// Usage:
///   nf                                  # interactive REPL
///   nf --url https://example.com        # open URL on launch
///   nf --stealth --cookies cookies.json # stealth + inject cookies
///   echo "navigate https://x.com\nsnap" | nf   # pipe commands
///
/// Commands (one per line):
///   navigate <url>            Navigate to URL
///   snap / snapshot           Print page snapshot
///   click @e<N>               Click element by @ref index
///   click css <selector>      Click element by CSS selector
///   click text <text>         Click element by visible text
///   type @e<N> <text>         Type into element by @ref
///   type css <selector> <txt> Type into element by CSS
///   scroll <px>               Scroll page (+down / -up)
///   wait <ms>                 Wait milliseconds
///   screenshot [file]         Save PNG (default /tmp/nf.png)
///   eval <js>                 Evaluate JavaScript, print result
///   cookies get               List all cookies (JSON)
///   cookies set <file>        Inject cookies from JSON/Netscape file
///   help                      Show this help
///   quit / exit               Close browser and exit
mod commands;

use std::io::{self, IsTerminal, Write};

use clap::Parser;
use night_fury_cli_core::output::OutputMode;
use night_fury_cli_core::repl::{CommandHandler, ReplEngine};
use night_fury_core::BrowserSession;

#[derive(Parser)]
#[command(name = "nf", about = "Night Fury browser CLI", version)]
struct Cli {
    /// Navigate to this URL on launch.
    #[arg(long, short)]
    url: Option<String>,

    /// Use stealth Chrome profile (Cloudflare-bypass).
    /// Default: stealth is always on (ChaserProfile is applied automatically).
    #[arg(long, default_value_t = false)]
    headed: bool,

    /// Load cookies from a JSON or Netscape cookie file on startup.
    #[arg(long, short, value_name = "FILE")]
    cookies: Option<String>,

    /// Viewport width in pixels (default 1440).
    #[arg(long, default_value_t = 1440)]
    width: u32,

    /// Viewport height in pixels (default 900).
    #[arg(long, default_value_t = 900)]
    height: u32,

    /// Proxy server URL (e.g. http://user:pass@host:port, socks5://host:port).
    #[arg(long, value_name = "URL")]
    proxy: Option<String>,

    /// Output JSON for agent workflows.
    #[arg(long, default_value_t = false)]
    json: bool,
}

struct NfHandler {
    session: BrowserSession,
    mode: OutputMode,
}

impl CommandHandler for NfHandler {
    async fn dispatch(&mut self, line: &str) -> bool {
        commands::dispatch(&self.session, line, self.mode).await
    }
}

// ---------------------------------------------------------------------------
// Entry point
// ---------------------------------------------------------------------------

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let cli = Cli::parse();

    let is_tty = io::stdin().is_terminal();

    if is_tty {
        eprintln!("🌙 Night Fury CLI  (type 'help' for commands, 'quit' to exit)");
    }

    // Launch browser
    if is_tty {
        eprint!("Launching browser…");
        let _ = io::stderr().flush();
    }
    let mut builder = BrowserSession::builder()
        .headed(cli.headed)
        .viewport(cli.width, cli.height);
    if let Some(proxy_url) = cli.proxy {
        builder = builder.proxy(proxy_url);
    }
    let session = builder
        .build()
        .await
        .map_err(|e| anyhow::anyhow!("browser launch failed: {e}"))?;

    if is_tty {
        eprintln!(" ready ✅");
    }

    // Inject cookies if provided
    if let Some(ref path) = cli.cookies {
        match night_fury_cli_core::cookie_loader::load_cookies(path) {
            Ok(cookies) => {
                // Navigate first so origin is set
                if cli.url.is_none() {
                    // We don't know the domain yet — skip automatic injection,
                    // user can call `cookies set` after navigating.
                    if is_tty {
                        eprintln!(
                            "⚠️  --cookies requires --url to set the origin first. \
                             Use `cookies set {path}` after navigating."
                        );
                    }
                } else {
                    let msg = session
                        .set_cookies(cookies)
                        .await
                        .unwrap_or_else(|e| format!("cookie inject error: {e}"));
                    if is_tty {
                        eprintln!("🍪 {msg}");
                    }
                }
            }
            Err(e) => eprintln!("⚠️  Could not load cookies from {path}: {e}"),
        }
    }

    // Navigate to initial URL
    if let Some(ref url) = cli.url {
        match session.navigate(url).await {
            Ok(msg) => {
                if is_tty {
                    eprintln!("{msg}");
                }
            }
            Err(e) => eprintln!("navigation error: {e}"),
        }

        // Inject cookies after navigation (correct origin is now set)
        if let Some(ref path) = cli.cookies {
            if let Ok(cookies) = night_fury_cli_core::cookie_loader::load_cookies(path) {
                let msg = session
                    .set_cookies(cookies)
                    .await
                    .unwrap_or_else(|e| format!("cookie inject error: {e}"));
                if is_tty {
                    eprintln!("🍪 {msg}");
                }
                // Reload so cookies take effect
                let _ = session.navigate(url).await;
            }
        }
    }

    // -----------------------------------------------------------------------
    // REPL loop
    // -----------------------------------------------------------------------
    let mode = if cli.json {
        OutputMode::Json
    } else {
        OutputMode::Human
    };
    let mut handler = NfHandler { session, mode };
    ReplEngine::new("nf> ").run(&mut handler).await?;

    Ok(())
}
