use serde::{Deserialize, Deserializer};

use crate::types::{FollowStatus, MangaId, UserId, UserRating};

/// This struct should not be used directly.
#[derive(Debug, Deserialize, Clone, PartialOrd, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct UserMangaPartial {
    user_id: UserId,
    manga_id: MangaId,
    manga_title: String,
    follow_type: FollowStatus,
    volume: String,
    chapter: String,
    #[serde(deserialize_with = "parse_rating")]
    rating: UserRating,
}

impl UserMangaPartial {
    pub fn user_id(&self) -> &UserId {
        &self.user_id
    }

    pub fn manga_id(&self) -> &MangaId {
        &self.manga_id
    }

    pub fn manga_title(&self) -> &String {
        &self.manga_title
    }

    pub fn follow_type(&self) -> &FollowStatus {
        &self.follow_type
    }

    pub fn volume(&self) -> &String {
        &self.volume
    }

    pub fn chapter(&self) -> &String {
        &self.chapter
    }

    pub fn rating(&self) -> &UserRating {
        &self.rating
    }
}

/// Custom deserializer for the `rating` field.
///
/// This returns the parsed `UserRating` variant
fn parse_rating<'de, D>(d: D) -> Result<UserRating, D::Error>
where
    D: Deserializer<'de>,
{
    Deserialize::deserialize(d).map(|rating: Option<_>| rating.unwrap_or(UserRating::NoRating))
}
