use anyhow::{bail, Context, Result};
use hashtree_network::types::{SignalingMessage, NOSTR_KIND_HASHTREE};
use hashtree_network::{decode_signaling_event, encode_signaling_event};
use nostr_sdk::prelude::*;
use std::env;
use std::io::{self, Read};

const SENDER_SECRET_HEX: &str = "0101010101010101010101010101010101010101010101010101010101010101";
const RECIPIENT_SECRET_HEX: &str =
    "0202020202020202020202020202020202020202020202020202020202020202";
const INTEROP_SDP: &str = "v=0\r\ns=hashtree-signaling-interop\r\n";

fn keys_from_hex(secret_hex: &str) -> Result<Keys> {
    let secret_bytes = hex::decode(secret_hex).context("decode secret key hex")?;
    let secret = SecretKey::from_slice(&secret_bytes).context("parse secret key")?;
    Ok(Keys::new(secret))
}

fn interop_message(sender_peer_id: String, recipient_peer_id: String) -> SignalingMessage {
    SignalingMessage::Offer {
        peer_id: sender_peer_id,
        target_peer_id: recipient_peer_id,
        sdp: INTEROP_SDP.to_string(),
    }
}

fn encode_offer() -> Result<()> {
    let sender_keys = keys_from_hex(SENDER_SECRET_HEX)?;
    let recipient_keys = keys_from_hex(RECIPIENT_SECRET_HEX)?;
    let sender_peer_id = sender_keys.public_key().to_hex();
    let recipient_peer_id = recipient_keys.public_key().to_hex();
    let msg = interop_message(sender_peer_id.clone(), recipient_peer_id);
    let event = encode_signaling_event(
        &sender_keys,
        &sender_peer_id,
        &msg,
        Kind::Ephemeral(NOSTR_KIND_HASHTREE),
    )?;
    println!("{}", serde_json::to_string(&event)?);
    Ok(())
}

fn decode_offer() -> Result<()> {
    let recipient_keys = keys_from_hex(RECIPIENT_SECRET_HEX)?;
    let recipient_peer_id = recipient_keys.public_key().to_hex();
    let mut input = String::new();
    io::stdin()
        .read_to_string(&mut input)
        .context("read event json")?;
    let event: Event = serde_json::from_str(&input).context("parse event json")?;
    let decoded = decode_signaling_event(
        &event,
        &recipient_peer_id,
        &recipient_keys.public_key().to_hex(),
        &recipient_keys,
    )
    .context("decode signaling event")?;
    println!("{}", serde_json::to_string(&decoded)?);
    Ok(())
}

fn print_keys() -> Result<()> {
    let sender_keys = keys_from_hex(SENDER_SECRET_HEX)?;
    let recipient_keys = keys_from_hex(RECIPIENT_SECRET_HEX)?;
    println!(
        "{}",
        serde_json::json!({
            "senderSecretHex": SENDER_SECRET_HEX,
            "senderPubkey": sender_keys.public_key().to_hex(),
            "recipientSecretHex": RECIPIENT_SECRET_HEX,
            "recipientPubkey": recipient_keys.public_key().to_hex(),
            "sdp": INTEROP_SDP,
        })
    );
    Ok(())
}

fn main() -> Result<()> {
    match env::args().nth(1).as_deref() {
        Some("encode-offer") => encode_offer(),
        Some("decode-offer") => decode_offer(),
        Some("keys") => print_keys(),
        Some(other) => bail!("unknown command: {other}"),
        None => bail!("usage: signaling_fixture <encode-offer|decode-offer|keys>"),
    }
}
