use serde::Deserialize;

use crate::types::{MangaDexResponseStatus, StatusCode};
use crate::v2::responses::{ErrorResponse, ResponseType};

#[derive(Debug, Deserialize, Clone, PartialOrd, PartialEq)]
#[serde(untagged)]
pub enum MangaCoversResponseType {
    Ok(MangaCoversResponse),
    Err(ErrorResponse),
}

impl ResponseType for MangaCoversResponseType {
    type OkOutput = MangaCoversResponse;

    /// Check if the endpoint response is ok.
    fn is_ok(&self) -> bool {
        matches!(self, Self::Ok(_))
    }

    /// Get the data from the endpoint if the response is ok.
    fn ok(self) -> Option<Self::OkOutput> {
        match self {
            Self::Ok(data) => Some(data),
            _ => None,
        }
    }
}

/// List of covers belonging to a manga.
///
/// Response from the `/api/v2/manga/{id}/covers` endpoint.
#[derive(Debug, Deserialize, Clone, PartialOrd, PartialEq)]
pub struct MangaCoversResponse {
    code: StatusCode,
    status: MangaDexResponseStatus,
    data: Vec<CoverInfo>,
}

impl MangaCoversResponse {
    pub fn code(&self) -> &StatusCode {
        &self.code
    }

    pub fn status(&self) -> &MangaDexResponseStatus {
        &self.status
    }

    pub fn data(&self) -> &Vec<CoverInfo> {
        &self.data
    }
}

/// This struct should not be used directly
#[derive(Debug, Deserialize, Clone, PartialOrd, PartialEq)]
pub struct CoverInfo {
    volume: String,
    url: String,
}

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

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