use crate::constants::USER_ME;
use crate::types::{FollowStatus, HentaiMode, UserId};
use crate::v2::builder::UserRequestError;
use crate::v2::responses::UserFollowedUpdatesResponseType;
use crate::v2::MangaDexV2;
use crate::MangaDexClient;

/// Builder for the `/api/v2/user/{id}/followed-updates` endpoint.
pub struct GetUserFollowedUpdatesBuilder<'a> {
    md_client: &'a MangaDexV2,
    id: Option<UserId>,
    me: bool,
    page: Option<u32>,
    follow_status: Option<FollowStatus>,
    hentai_mode: Option<HentaiMode>,
    include_delayed: Option<bool>,
}

impl<'a> GetUserFollowedUpdatesBuilder<'a> {
    pub fn new(md_client: &'a MangaDexV2) -> Self {
        Self {
            md_client,
            id: None,
            me: false,
            page: None,
            follow_status: None,
            hentai_mode: None,
            include_delayed: None,
        }
    }

    /// Set the numeric user ID.
    ///
    /// This takes priority over the `me` field if both are set.
    pub fn user_id(&mut self, id: UserId) -> &mut Self {
        self.id = Some(id);
        self
    }

    /// Set `true` to use the current cookie-authenticated user.
    pub fn me(&mut self, me: bool) -> &mut Self {
        self.me = me;
        self
    }

    /// Set the current page of the paginated results.
    ///
    /// Default returns all chapters without pagination.
    pub fn page(&mut self, page: u32) -> &mut Self {
        self.page = Some(page);
        self
    }

    /// Filter the results by the follow type.
    pub fn follow_status(&mut self, follow_status: FollowStatus) -> &mut Self {
        self.follow_status = Some(follow_status);
        self
    }

    /// Filter the results based on whether the titles are marked as hentai.
    pub fn hentai_mode(&mut self, hentai_mode: HentaiMode) -> &mut Self {
        self.hentai_mode = Some(hentai_mode);
        self
    }

    /// Include delayed chapters in the results.
    pub fn include_delayed(&mut self, include_delayed: bool) -> &mut Self {
        self.include_delayed = Some(include_delayed);
        self
    }

    pub async fn send(&self) -> Result<UserFollowedUpdatesResponseType, UserRequestError> {
        let id = if let Some(id) = self.id {
            id.to_string()
        } else if self.me {
            String::from(USER_ME)
        } else {
            return Err(UserRequestError::IDNotProvidedError);
        };

        let mut params = Vec::new();
        if let Some(page) = self.page {
            params.push(("p", page.to_string()));
        }
        if let Some(follow_status) = &self.follow_status {
            params.push(("type", (*follow_status as u8).to_string()));
        }
        if let Some(hentai_mode) = &self.hentai_mode {
            params.push(("hentai", (*hentai_mode as u8).to_string()));
        }
        if let Some(include_delayed) = self.include_delayed {
            params.push(("delayed", include_delayed.to_string()));
        }

        Ok(self
            .md_client
            .client()
            .get(&format!(
                "{base_url}/user/{user_id}/followed-updates",
                base_url = self.md_client.api_url(),
                user_id = id
            ))
            .query(&params)
            .send()
            .await?
            .json::<UserFollowedUpdatesResponseType>()
            .await?)
    }
}
