//! `relicario generate` — emit a fresh password or BIP39 passphrase.

use anyhow::Result;

pub fn cmd_generate(
    length: Option<u32>,
    bip39: bool,
    words: Option<u32>,
    symbols: Option<String>,
    separator: Option<String>,
) -> Result<()> {
    use relicario_core::{
        generate_passphrase, generate_password, Capitalization, CharClasses,
        GeneratorRequest, SymbolCharset,
    };

    // If we're inside a vault, unlock and pull `generator_defaults`. Outside
    // a vault, this stays a fast standalone CSPRNG tool (no unlock prompt).
    let vault_defaults: Option<GeneratorRequest> = if crate::helpers::vault_dir().is_ok() {
        let vault = crate::session::UnlockedVault::unlock_interactive()?;
        Some(vault.load_settings()?.generator_defaults)
    } else {
        None
    };

    // `--bip39` flag forces Bip39 mode; otherwise use whatever mode the
    // vault default is in (Random when no vault).
    let use_bip39 = bip39 || matches!(vault_defaults, Some(GeneratorRequest::Bip39 { .. }));

    let output = if use_bip39 {
        let (def_words, def_sep, def_cap) = match &vault_defaults {
            Some(GeneratorRequest::Bip39 { word_count, separator, capitalization }) => {
                (*word_count, separator.clone(), *capitalization)
            }
            _ => (5, " ".to_string(), Capitalization::Lower),
        };
        generate_passphrase(&GeneratorRequest::Bip39 {
            word_count: words.unwrap_or(def_words),
            separator: separator.unwrap_or(def_sep),
            capitalization: def_cap,
        })?
    } else {
        let (def_length, def_classes, def_charset) = match &vault_defaults {
            Some(GeneratorRequest::Random { length, classes, symbol_charset }) => {
                (*length, *classes, symbol_charset.clone())
            }
            _ => (
                20,
                CharClasses { lower: true, upper: true, digits: true, symbols: true },
                SymbolCharset::SafeOnly,
            ),
        };
        let symbol_charset = match symbols.as_deref() {
            None => def_charset,
            Some("safe") => SymbolCharset::SafeOnly,
            Some("extended") => SymbolCharset::Extended,
            Some(other) => SymbolCharset::Custom(other.to_string()),
        };
        generate_password(&GeneratorRequest::Random {
            length: length.unwrap_or(def_length),
            classes: def_classes,
            symbol_charset,
        })?
    };

    println!("{}", output.as_str());
    Ok(())
}
