use std::collections::HashMap;

use log::warn;
use nostr_sdk::prelude::*;

use super::core::{CaracalUser, UserError};
use crate::relays::default_relays;
use duration_str::parse as dur_parse;

impl CaracalUser {
    pub async fn advertise_relay_list(
        &self,
        force: bool,
    ) -> Result<(), UserError> {
        let relay_config = self.relay_list_config();

        let mut relay_metadata: HashMap<RelayUrl, Option<RelayMetadata>> =
            HashMap::new();

        for rurl in relay_config.read_relays {
            if let Err(err) = self.client.add_read_relay(&rurl).await {
                warn!("Failed to add read relay: {err}");
            }

            relay_metadata.insert(rurl, Some(RelayMetadata::Read));
        }

        for wurl in relay_config.write_relays {
            if let Err(err) = self.client.add_write_relay(&wurl).await {
                warn!("Failed to add write relay: {err}");
            }

            relay_metadata.insert(wurl, Some(RelayMetadata::Write));
        }

        let until = Timestamp::now() - dur_parse("1d").unwrap();

        // Don't advertise if we sent one recently and have a copy in the db
        if let Ok(last_relay_list) = self
            .db_query_first(
                Filter::new()
                    .kind(Kind::RelayList)
                    .author(self.public_key().await?),
            )
            .await
            && last_relay_list.created_at > until
            && !force
        {
            return Err(UserError::NotAdvertisingRelayList);
        }

        let relay_list_builder = EventBuilder::relay_list(relay_metadata);

        self.client
            .send_event_builder_to(default_relays(), relay_list_builder)
            .await?;

        /* Send (fixed list for now to make the DMs UI work) inbox relays event */
        let inboxr: Vec<&str> =
            vec!["wss://nos.lol", "wss://nostr.bitcoiner.social"];

        let inbox_relays_builder = EventBuilder::new(Kind::InboxRelays, "")
            .tags(
                inboxr
                    .into_iter()
                    .map(|ir| Tag::custom(TagKind::Relay, vec![ir])),
            );

        self.client
            .send_event_builder_to(default_relays(), inbox_relays_builder)
            .await?;

        Ok(())
    }
}
