use scraper::{Html, Selector};

use crate::helpers::parse_manga_id_from_scraped_url;
use crate::types::MangaResultsSortBy;
use crate::web_scrape::responses::MangaScrapeInfo;
use crate::MangaDexClient;

/// Builder for the `/titles/7/{page}` endpoint.
///
/// By default, 50 results are returned on the page.
pub struct GetMostPopularMangaScrapeBuilder<'a> {
    md_client: &'a (dyn MangaDexClient + 'a),
    page: u32,
    use_cover_thumbnail: bool,
}

impl<'a> GetMostPopularMangaScrapeBuilder<'a> {
    /// Create a new builder instance for fetching the most popular manga.
    pub fn new(md_client: &'a dyn MangaDexClient) -> GetMostPopularMangaScrapeBuilder<'a> {
        Self {
            md_client,
            page: 1,
            use_cover_thumbnail: false,
        }
    }

    /// Set the page to fetch.
    pub fn page(&mut self, page: u32) -> &mut Self {
        self.page = page;
        self
    }

    /// Choose to use the thumbnail version of the cover image.
    ///
    /// If false, it will use the full-resolution image.
    pub fn use_cover_thumbnail(&mut self, use_cover_thumbnail: bool) -> &mut Self {
        self.use_cover_thumbnail = use_cover_thumbnail;
        self
    }

    /// Send the request to MangaDex.
    pub async fn send(&self) -> Result<Vec<MangaScrapeInfo>, reqwest::Error> {
        let resp = self
            .md_client
            .client()
            .get(&format!(
                "{base_url}/titles/{sort_by}/{page}",
                base_url = self.md_client.base_url(),
                sort_by = (MangaResultsSortBy::RatingDescending as u8).to_string(),
                page = self.page
            ))
            .send()
            .await?;

        let body = resp.text().await?;
        let fragment = Html::parse_document(&body);
        // Selecting the chapter URL is difficult since there are no unique identifiers.
        let title_selector = Selector::parse("a.manga_title").unwrap();

        Ok(fragment
            .select(&title_selector)
            .filter_map(|el| {
                let title: String = el.text().collect();
                let url = el.value().attr("href")?;
                let manga_id = parse_manga_id_from_scraped_url(url)?;

                Some(MangaScrapeInfo::new(
                    self.md_client.base_url(),
                    manga_id,
                    title,
                    self.use_cover_thumbnail,
                ))
            })
            .collect())
    }
}
