//!  Account related types
use crate::types::{event::Error, Content, Event, Tag, UnsignedEvent};
use chrono::{DateTime, Utc};
use rand::rngs::OsRng;
use secp256k1::{KeyPair, Message, Secp256k1, SecretKey, XOnlyPublicKey};

/// Nostr User account
#[derive(Debug, Clone)]
pub struct Account(KeyPair);

impl Account {
    /// Get the public key from a user
    pub fn public_key(&self) -> XOnlyPublicKey {
        self.0.x_only_public_key().0
    }

    /// Creates a new event with the given content
    pub fn sign_content(
        &self,
        tags: Vec<Tag>,
        content: Content,
        created_at: Option<DateTime<Utc>>,
    ) -> Result<Event, Error> {
        let unsigned_event =
            UnsignedEvent::new(self.public_key().into(), tags, content, created_at)?;
        let id = unsigned_event.id()?;
        let to_sign = Message::from_slice(&*id)?;
        let secp = Secp256k1::new();
        let signature = secp.sign_schnorr_no_aux_rand(&to_sign, &self.0);

        Event::new(unsigned_event, signature.into())
    }
}

impl From<KeyPair> for Account {
    fn from(keypair: KeyPair) -> Self {
        Self(keypair)
    }
}

impl From<&SecretKey> for Account {
    fn from(secret_key: &SecretKey) -> Self {
        Self(KeyPair::from_secret_key(&Secp256k1::new(), secret_key))
    }
}

impl From<SecretKey> for Account {
    fn from(secret_key: SecretKey) -> Self {
        Self(KeyPair::from_secret_key(&Secp256k1::new(), &secret_key))
    }
}

impl Default for Account {
    fn default() -> Self {
        let secp = Secp256k1::new();
        let (secret_key, _) = secp.generate_keypair(&mut OsRng);
        secret_key.into()
    }
}
