use anyhow::Result;
use bpx_api_client::BpxClient;
use owo_colors::OwoColorize;

use crate::client;
use crate::config::{self, Profile};
use crate::style::Styles;

/// Run setup either interactively (default) or non-interactively with flags.
/// Non-interactive mode is for AI agents and scripts.
pub async fn run(
    secret: Option<&str>,
    profile_name: Option<&str>,
    base_url: Option<&str>,
    ws_url: Option<&str>,
) -> Result<()> {
    let s = Styles::new();

    let (profile, api_secret, base, ws) = if let Some(sec) = secret {
        // Non-interactive mode (agent-friendly)
        (
            profile_name.unwrap_or("default").to_string(),
            sec.to_string(),
            base_url
                .unwrap_or("https://api.backpack.exchange")
                .to_string(),
            ws_url.unwrap_or("wss://ws.backpack.exchange").to_string(),
        )
    } else {
        // Interactive mode (human-friendly)
        use dialoguer::{Confirm, Input, Password};

        println!();
        println!("{}", "  Backpack Exchange CLI Setup".style(s.cyan));
        println!();
        println!("  To get your API key:");
        println!(
            "  1. Go to {}",
            "https://backpack.exchange/settings/api-keys".style(s.bold)
        );
        println!("  2. Create a new API key");
        println!(
            "  3. Copy the {} (not the public key)",
            "secret key".style(s.bold)
        );
        println!();

        let profile: String = Input::new()
            .with_prompt("Profile name")
            .default("default".to_string())
            .interact_text()?;

        let api_secret: String = loop {
            let secret: String = Password::new().with_prompt("API secret").interact()?;
            if secret.is_empty() {
                eprintln!("  {} API secret cannot be empty.", "✗".style(s.red));
                continue;
            }
            if secret.len() < 40 {
                eprintln!(
                    "  {} Secret looks too short. Make sure you copied the full key.",
                    "✗".style(s.red)
                );
                continue;
            }
            break secret;
        };

        // Validate the key by calling get_balances()
        let spinner = client::spinner("Verifying API key...");
        let validation = validate_key(&api_secret).await;
        spinner.finish_and_clear();

        match validation {
            Ok(count) => {
                println!(
                    "  {} API key verified — {} assets in account",
                    "✓".style(s.green),
                    count
                );
            }
            Err(e) => {
                eprintln!("  {} Verification failed: {}", "✗".style(s.red), e);
                let save_anyway = Confirm::new()
                    .with_prompt("  Save anyway?")
                    .default(false)
                    .interact()?;
                if !save_anyway {
                    println!("  Setup cancelled.");
                    return Ok(());
                }
            }
        }

        let base = "https://api.backpack.exchange".to_string();
        let ws = "wss://ws.backpack.exchange".to_string();

        (profile, api_secret, base, ws)
    };

    let p = Profile {
        api_secret: Some(api_secret),
        base_url: if base == "https://api.backpack.exchange" {
            None
        } else {
            Some(base)
        },
        ws_url: if ws == "wss://ws.backpack.exchange" {
            None
        } else {
            Some(ws)
        },
    };

    config::save_config(&profile, &p)?;

    // Fetch market count for the success message
    let market_count = fetch_market_count().await;

    println!();
    println!("{}", "  ✓ Setup complete!".style(s.green));
    if let Some(count) = market_count {
        println!("  {} markets available", count.to_string().style(s.bold));
    }
    println!();
    println!("  Next steps:");
    println!(
        "    {}                 Launch the dashboard",
        "bpx".style(s.bold)
    );
    println!(
        "    {}    View your balances",
        "bpx account balances".style(s.bold)
    );
    println!(
        "    {}     Learn order placement",
        "bpx order place --help".style(s.bold)
    );
    println!();

    Ok(())
}

/// Validate a secret key by attempting to fetch balances.
/// Returns the number of assets on success.
async fn validate_key(secret: &str) -> Result<usize> {
    let client = BpxClient::builder()
        .base_url("https://api.backpack.exchange")
        .secret(secret)
        .build()
        .map_err(|e| anyhow::anyhow!("{e}"))?;
    let balances = client
        .get_balances()
        .await
        .map_err(|e| anyhow::anyhow!("{e}"))?;
    Ok(balances.len())
}

/// Fetch the total number of markets (best-effort, returns None on failure).
async fn fetch_market_count() -> Option<usize> {
    let client = BpxClient::builder()
        .base_url("https://api.backpack.exchange")
        .build()
        .ok()?;
    client.get_markets().await.ok().map(|m| m.len())
}
