use std::str::FromStr;
use url::Url;

pub struct Query(Url);

impl Query {
    pub fn new(
        announce_url: &str,
        info_hash: &[u8; 20],
        port: u16,
    ) -> Result<Self, Box<dyn std::error::Error>> {
        fn url_encode_bytes(bytes: &[u8]) -> String {
            bytes.iter().map(|b| format!("%{:02x}", b)).collect()
        }

        let mut url = Url::from_str(announce_url)?;

        let mut rng = rand::rng();
        let mut peer_id = [0u8; 20];
        rand::RngExt::fill(&mut rng, &mut peer_id);

        url.set_query(Some(&format!(
            "info_hash={}&peer_id={}&port={port}&uploaded=0&downloaded=0&left=1000&compact=1",
            url_encode_bytes(info_hash),
            url_encode_bytes(&peer_id)
        )));

        Ok(Self(url))
    }
    pub fn url(&self) -> &Url {
        &self.0
    }
}

impl std::fmt::Display for Query {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}
