use std::hash::{DefaultHasher, Hash, Hasher};

use itertools::Itertools;
use nostr_sdk::prelude::*;

pub trait EventExt {
    fn uniq_id(&self) -> u64;
    fn extract_public_keys(&self) -> Vec<PublicKey>;
}

impl EventExt for Event {
    fn uniq_id(&self) -> u64 {
        let mut hasher = DefaultHasher::new();
        let mut pubkeys: Vec<PublicKey> = self.extract_public_keys();
        pubkeys.sort();
        pubkeys.hash(&mut hasher);
        hasher.finish()
    }

    fn extract_public_keys(&self) -> Vec<PublicKey> {
        let mut public_keys: Vec<PublicKey> = self.tags.public_keys().collect();
        public_keys.push(self.pubkey);

        public_keys.into_iter().unique().collect()
    }
}

impl EventExt for UnsignedEvent {
    fn uniq_id(&self) -> u64 {
        let mut hasher = DefaultHasher::new();
        let mut pubkeys: Vec<PublicKey> = vec![];

        // Add all public keys from event
        pubkeys.push(self.pubkey);
        pubkeys.extend(self.tags.public_keys().collect::<Vec<_>>());

        // Generate unique hash
        pubkeys
            .into_iter()
            .unique()
            .sorted()
            .collect::<Vec<_>>()
            .hash(&mut hasher);

        hasher.finish()
    }

    fn extract_public_keys(&self) -> Vec<PublicKey> {
        let mut public_keys: Vec<PublicKey> = self.tags.public_keys().collect();
        public_keys.push(self.pubkey);
        public_keys.into_iter().unique().sorted().collect()
    }
}
