use crate::peer::Peer;
use crate::peer_store::SharedPeerStore;
use libp2p::PeerId;
use std::time::Duration;
use tokio::time::{interval, Instant};

pub struct DiscoveryConfig {
    pub scan_interval_secs: u64,
    pub enable_mdns: bool,
}

impl Default for DiscoveryConfig {
    fn default() -> Self {
        Self {
            scan_interval_secs: 30,
            enable_mdns: true,
        }
    }
}

pub struct Discovery {
    peer_store: SharedPeerStore,
    config: DiscoveryConfig,
}

impl Discovery {
    pub fn new(peer_store: SharedPeerStore, config: DiscoveryConfig) -> Self {
        Self { peer_store, config }
    }

    pub async fn start(self) {
        tracing::info!(
            "Starting discovery with scan interval {}s",
            self.config.scan_interval_secs
        );

        let mut scan_interval = interval(Duration::from_secs(self.config.scan_interval_secs));
        let start = Instant::now();

        loop {
            scan_interval.tick().await;
            let elapsed = start.elapsed();
            tracing::debug!("Discovery scan at {:?}", elapsed);

            self.peer_store.get_all_peers().iter().for_each(|peer| {
                tracing::debug!(
                    "Peer {}: {} addresses, public_ip: {:?}",
                    peer.peer_id,
                    peer.addresses.len(),
                    peer.public_ip
                );
            });
        }
    }
}

pub fn handle_peer_discovered(peer_store: &SharedPeerStore, peer_id: PeerId) {
    let peer = Peer::new(peer_id);
    peer_store.add_peer(peer);
    tracing::info!("Peer discovered via mDNS: {}", peer_id);
}

pub fn handle_peer_expired(peer_store: &SharedPeerStore, peer_id: PeerId) {
    peer_store.remove_peer(&peer_id);
    tracing::info!("Peer expired from mDNS: {}", peer_id);
}