use crate::db::Database;
use crate::identity::{IdKeyData, Identity, unescape};
use std::path::Path;
use std::process::exit;

pub fn import_key(db_path: &Path, key: String, insert_anyway: bool) -> anyhow::Result<()> {
    // decode the key
    let components = key.split("/").collect::<Vec<_>>();
    if components.len() != 4 || components[0] != "sage" {
        eprintln!("not a sage key (looks like sage/key/name/email");
        eprintln!("to import a raw age key without an identity, add it to the database manually");
        exit(1);
    }

    let [_sentinel, key, name, email] = components.as_slice() else {
        unreachable!()
    };

    let name = unescape(name.to_string())?;
    let email = unescape(email.to_string())?;

    let keys = match &key[0..3] {
        "age" => IdKeyData::Peer(key.to_string()),
        "AGE" => IdKeyData::Local(key.to_string()),
        _ => {
            eprintln!("unsupported age key type; is this a sage key?");
            exit(1);
        }
    };

    let identity = Identity { name, email, keys };

    let mut db = Database::load_or_create(db_path)?;

    for key in &db.keys {
        if key.keys.keyid()? == identity.keys.keyid()? {
            println!(
                "key {} already exists in database, skipping",
                key.keys.keyid()?
            );
            return Ok(());
        }

        if key.name == identity.name && key.email == identity.email && !insert_anyway {
            eprintln!("database already has a key for {:?}", identity);
            eprintln!("to import anyway, run again with --import-anyway");
            exit(1);
        }
    }

    db.keys.push(identity.clone());

    db.write(db_path)?;

    println!(
        "imported {:?} (keyid {}) successfully",
        identity,
        identity.keys.keyid()?
    );

    Ok(())
}
