//! `relicario recovery-qr {generate,unwrap}` — last-resort vault-key escape hatch.

use anyhow::{Context, Result};

use crate::RecoveryQrCmd;

pub fn cmd_recovery_qr(cmd: RecoveryQrCmd) -> Result<()> {
    match cmd {
        RecoveryQrCmd::Generate => cmd_recovery_qr_generate(),
        RecoveryQrCmd::Unwrap   => cmd_recovery_qr_unwrap(),
    }
}

fn cmd_recovery_qr_generate() -> Result<()> {
    use relicario_core::{generate_recovery_qr, imgsecret};
    use zeroize::Zeroizing;

    let image_path = crate::session::get_image_path()?;
    let image_bytes = std::fs::read(&image_path)
        .with_context(|| format!("read reference image {}", image_path.display()))?;
    let image_secret = imgsecret::extract(&image_bytes)
        .context("extract image secret")?;

    let passphrase = Zeroizing::new(
        rpassword::prompt_password("Enter vault passphrase: ")
            .context("read passphrase")?
    );

    let payload = generate_recovery_qr(passphrase.as_str(), &image_secret)
        .map_err(|e| anyhow::anyhow!("{e}"))?;

    use qrcode::{EcLevel, QrCode, render::unicode};
    let code = QrCode::with_error_correction_level(payload.as_bytes(), EcLevel::M)
        .expect("valid payload");
    let image = code
        .render::<unicode::Dense1x2>()
        .dark_color(unicode::Dense1x2::Dark)
        .light_color(unicode::Dense1x2::Light)
        .build();
    println!("{image}");
    println!("Recovery QR generated. Print or photograph this code and store it securely.");
    println!("The QR has NOT been saved to disk.");
    Ok(())
}

fn cmd_recovery_qr_unwrap() -> Result<()> {
    use relicario_core::unwrap_recovery_qr;
    use std::io::BufRead;
    use zeroize::Zeroizing;

    println!("Paste the base64 recovery QR payload and press Enter:");
    let stdin = std::io::stdin();
    let payload_b64 = stdin.lock().lines().next()
        .context("no input")??;
    let payload_b64 = payload_b64.trim().to_owned();

    let bytes = data_encoding::BASE64.decode(payload_b64.as_bytes())
        .map_err(|e| anyhow::anyhow!("base64 decode: {e}"))?;

    let passphrase = Zeroizing::new(
        rpassword::prompt_password("Enter passphrase: ")
            .context("read passphrase")?
    );

    let secret = unwrap_recovery_qr(&bytes, passphrase.as_str())
        .map_err(|e| anyhow::anyhow!("{e}"))?;
    println!("image_secret: {}", hex::encode(secret.as_ref()));
    Ok(())
}
