//! `relicario add <kind>` — create a new item of the given type.
//!
//! `cmd_add` resolves `title` / non-secret prompts, then delegates to the
//! shared builders in `commands/item_build.rs`. Group / tags / favorite are
//! set AFTER the build so the builders stay portable to the org vault.

use anyhow::Result;

use crate::AddKind;
use crate::commands::item_build as ib;
use crate::prompt::{prompt_or_flag, prompt_or_flag_optional};

pub fn cmd_add(kind: AddKind) -> Result<()> {
    let vault = crate::session::UnlockedVault::unlock_interactive()?;
    let mut manifest = vault.load_manifest()?;

    let item = match kind {
        AddKind::Login { title, username, url, password_prompt, password, password_stdin, group, tags, favorite, totp_qr } => {
            let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
            let username = prompt_or_flag_optional(username, "Username", |s| Ok(s.to_string()))?;
            let url = prompt_or_flag_optional(url, "URL", |s| Ok(s.to_string()))?;
            let mut item = ib::build_login(title, username, url, password, password_stdin, password_prompt, totp_qr)?;
            item.group = group; item.tags = tags; item.favorite = favorite;
            item
        }
        AddKind::SecureNote { title, body_stdin, group, tags } => {
            // Per the v0.8.1 spec's unified secret model, a note body is a
            // multiline secret that always reads stdin to EOF. `body_stdin=false`
            // means "print the Ctrl-D hint" (interactive default); `true` suppresses
            // the hint for non-interactive use.
            // Secret-resolution rule: `commands/item_build.rs` `resolve_secret_multiline`.
            let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
            let mut item = ib::build_secure_note(title, None, body_stdin)?;
            item.group = group; item.tags = tags;
            item
        }
        AddKind::Identity { title, full_name, email, phone, date_of_birth, group, tags } => {
            let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
            let mut item = ib::build_identity(title, full_name, email, phone, date_of_birth)?;
            item.group = group; item.tags = tags;
            item
        }
        AddKind::Card { title, holder, expiry, kind, number_stdin, cvv_stdin, pin_stdin, group, tags } => {
            let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
            let mut item = ib::build_card(title, holder, expiry, &kind, number_stdin, cvv_stdin, pin_stdin)?;
            item.group = group; item.tags = tags;
            item
        }
        AddKind::Key { title, label, algorithm, material_stdin, group, tags } => {
            // public_key is None for the personal vault: the legacy `prompt_optional`
            // for it was unreachable (stdin already at EOF after the key-material read).
            // Org `add key` (Dev-B) supplies it via --public-key.
            let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
            let mut item = ib::build_key(title, label, algorithm, None, material_stdin)?;
            item.group = group; item.tags = tags;
            item
        }
        AddKind::Document { title, file, group, tags } => {
            let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
            let caps = vault.load_settings()?.attachment_caps;
            let (mut item, enc) = ib::build_document(title, file, vault.key(), caps.per_attachment_max_bytes)?;
            item.group = group; item.tags = tags;
            let att_dir = vault.root().join("attachments").join(item.id.as_str());
            std::fs::create_dir_all(&att_dir)?;
            std::fs::write(att_dir.join(format!("{}.enc", enc.id.as_str())), &enc.bytes)?;
            item
        }
        AddKind::Totp { title, issuer, label, secret, secret_stdin, period, digits, algorithm, group, tags } => {
            let title = prompt_or_flag(title, "Title", |s| Ok(s.to_string()))?;
            let mut item = ib::build_totp(title, issuer, label, secret, secret_stdin, period, digits, &algorithm)?;
            item.group = group; item.tags = tags;
            item
        }
    };

    vault.save_item(&item)?;
    manifest.upsert(&item);
    vault.after_manifest_change(&manifest)?;

    let mut paths: Vec<String> = vec![
        format!("items/{}.enc", item.id.as_str()),
        "manifest.enc".into(),
    ];
    for att in &item.attachments {
        paths.push(format!("attachments/{}/{}.enc", item.id.as_str(), att.id.as_str()));
    }
    let path_refs: Vec<&str> = paths.iter().map(|s| s.as_str()).collect();
    super::commit_paths(&vault, &format!("add: {} ({})", crate::helpers::sanitize_for_commit(&item.title), item.id.as_str()), &path_refs)?;

    eprintln!("Added: {} (id={})", item.title, item.id.as_str());
    Ok(())
}
