use std::collections::HashMap;
use crate::http_client::HttpClient;
use crate::error::Result;
use crate::models::{
    AsnInfoFullResponse, PrefixesListResponse, NetworkByCidrResponse,
    AsnRankListResponse, TorExitNodesResponse,
};

/// Network Engineering package — 7 endpoints.
#[derive(Clone)]
pub struct NetworkEngineeringApi {
    http: HttpClient,
}

impl NetworkEngineeringApi {
    pub fn new(http: HttpClient) -> Self { Self { http } }

    /// Returns extended ASN info including peers, transit, prefix counts, and service area.
    pub fn get_asn_info_full(&self, asn: &str, locality_language: &str) -> Result<AsnInfoFullResponse> {
        self.http.get("asn-info-full", asn_params(asn, locality_language))
    }

    /// Returns paginated upstream providers (ASNs this ASN receives traffic from).
    pub fn get_receiving_from(&self, asn: &str, batch_size: u32, offset: u32, locality_language: &str) -> Result<AsnInfoFullResponse> {
        let mut p = asn_params(asn, locality_language);
        p.insert("batchSize".to_string(), batch_size.to_string());
        p.insert("offset".to_string(), offset.to_string());
        self.http.get("asn-info-receiving-from", p)
    }

    /// Returns paginated downstream peers (ASNs this ASN provides transit to).
    pub fn get_transit_to(&self, asn: &str, batch_size: u32, offset: u32, locality_language: &str) -> Result<AsnInfoFullResponse> {
        let mut p = asn_params(asn, locality_language);
        p.insert("batchSize".to_string(), batch_size.to_string());
        p.insert("offset".to_string(), offset.to_string());
        self.http.get("asn-info-transit-to", p)
    }

    /// Returns paginated active BGP prefixes for an ASN. Set `ipv4 = false` for IPv6.
    pub fn get_bgp_prefixes(&self, asn: &str, ipv4: bool, batch_size: u32, offset: u32) -> Result<PrefixesListResponse> {
        let mut p = HashMap::new();
        p.insert("asn".to_string(), asn.to_string());
        p.insert("isv4".to_string(), if ipv4 { "true" } else { "false" }.to_string());
        p.insert("batchSize".to_string(), batch_size.to_string());
        p.insert("offset".to_string(), offset.to_string());
        self.http.get("prefixes-list", p)
    }

    /// Returns all networks announced on BGP within a CIDR range.
    pub fn get_networks_by_cidr(&self, cidr: &str, locality_language: &str) -> Result<NetworkByCidrResponse> {
        let mut p = HashMap::new();
        p.insert("cidr".to_string(), cidr.to_string());
        p.insert("localityLanguage".to_string(), locality_language.to_string());
        self.http.get("network-by-cidr", p)
    }

    /// Returns a paginated ranked list of all ASNs by IPv4 address space.
    pub fn get_asn_rank_list(&self, batch_size: u32, offset: u32) -> Result<AsnRankListResponse> {
        let mut p = HashMap::new();
        p.insert("batchSize".to_string(), batch_size.to_string());
        p.insert("offset".to_string(), offset.to_string());
        self.http.get("asn-rank-list", p)
    }

    /// Returns a paginated list of active Tor exit nodes.
    pub fn get_tor_exit_nodes(&self, batch_size: u32, offset: u32) -> Result<TorExitNodesResponse> {
        let mut p = HashMap::new();
        p.insert("batchSize".to_string(), batch_size.to_string());
        p.insert("offset".to_string(), offset.to_string());
        self.http.get("tor-exit-nodes-list", p)
    }
}

fn asn_params(asn: &str, locality_language: &str) -> HashMap<String, String> {
    let mut p = HashMap::new();
    p.insert("asn".to_string(), asn.to_string());
    p.insert("localityLanguage".to_string(), locality_language.to_string());
    p
}
