//! DNS pre-resolution cache for eliminating per-request DNS lookups.

use rustc_hash::FxHashMap;
use std::net::IpAddr;
use std::sync::{Arc, RwLock};

/// Cached DNS resolver that stores hostname to IP mappings.
#[derive(Clone)]
pub struct CachedDnsResolver {
    cache: Arc<RwLock<FxHashMap<String, Vec<IpAddr>>>>,
}

impl CachedDnsResolver {
    /// Create a new resolver with the given cache.
    pub fn new(cache: Arc<RwLock<FxHashMap<String, Vec<IpAddr>>>>) -> Self {
        Self { cache }
    }

    /// Pre-resolve a list of hostnames in parallel.
    pub async fn pre_resolve_hosts(&self, hostnames: &[String]) {
        let tasks: Vec<_> = hostnames
            .iter()
            .map(|host| {
                let cache = self.cache.clone();
                let host = host.clone();
                tokio::spawn(async move {
                    if let Ok(addrs) = tokio::net::lookup_host(format!("{host}:0")).await {
                        let ips: Vec<IpAddr> = addrs.map(|a| a.ip()).collect();
                        if !ips.is_empty() {
                            let mut guard = cache
                                .write()
                                .unwrap_or_else(std::sync::PoisonError::into_inner);
                            guard.insert(host, ips);
                        }
                    }
                })
            })
            .collect();
        for task in tasks {
            let _ = task.await;
        }
    }
}
