/*
 * Copyright (c) 2025, LJason. All Rights Reserved.
 */

//! 收藏夹相关
//!
//! [文档](https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/fav/list.md)

use serde::Deserialize;

use crate::{BiCoreError, BiliCore, BiliRequest};

/// 信息本体
#[derive(Debug, Deserialize)]
pub struct FavContentDetailList {
    /// 元数据
    pub info: FavInfo,
    /// 内容
    pub medias: Vec<FavContent>,
    /// 是否有下一页
    pub has_more: bool,
    /// 接口返回时间
    pub ttl: u64,
}

/// 收藏夹元数据
#[derive(Debug, Deserialize)]
pub struct FavInfo {
    /// 收藏夹 id
    /// - 原始id+创建者 mid 尾号2位
    pub id: u64,
    /// 收藏夹标题
    pub title: String,
    /// 收藏夹内容数量
    pub media_count: u16,
}

/// 收藏夹内容
#[derive(Debug, Deserialize)]
pub struct FavContent {
    /// 标题
    pub title: String,
    /// 视频稿件 bvid
    pub bvid: String,
    /// 类型: 2-视频稿件 12-音频 21-视频合集
    #[serde(rename = "type")]
    pub type_: u8,
    /// 失效: 0-正常 9-Up自己删除 1-其他原因删除
    pub attr: u8,
}

impl FavContent {
    const VALID: u8 = 0;
    const DELETED_BY_OTHERS: u8 = 1;
    const DELETED_BY_UP: u8 = 9;

    /// 检测是否有效
    ///
    /// # Errors
    ///
    /// - `String`: 错误信息
    pub fn validate(&self) -> Result<(), String> {
        match self.attr {
            Self::VALID => Ok(()),
            Self::DELETED_BY_OTHERS => Err(format!("{} 已被其他原因删除！", self.title)),
            Self::DELETED_BY_UP => Err(format!("{} 已被 Up 自己删除！", self.title)),
            _ => Err("未知错误！".into()),
        }
    }
}

impl BiliCore {
    /// # [获取收藏夹内容明细列表](https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/docs/fav/list.md#获取收藏夹内容明细列表)
    ///
    /// # 参数
    ///
    /// - `media_id`: 目标收藏夹mlid（完整id）
    /// - `ps`: 每页数量 1~40
    /// - `pn`: 页码
    ///
    /// # Errors
    ///
    /// 当网络请求失败、接口返回异常或解析响应数据出错时，将返回 [`BiCoreError`]。
    pub async fn fav_resource_list(&self, media_id: u64, ps: Option<u8>, pn: Option<u8>) -> Result<FavContentDetailList, BiCoreError> {
        // 默认每页最多 40 条
        const DEFAULT_PAGE_SIZE: u8 = 40;

        let media_id = media_id.to_string();
        let ps = ps.unwrap_or(DEFAULT_PAGE_SIZE).to_string();

        let mut params = vec![("media_id", media_id), ("ps", ps)];

        if let Some(pn) = pn {
            params.push(("pn", pn.to_string()));
        }

        self.get("x/v3/fav/resource/list").query(&params).core_send().await
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[allow(clippy::unwrap_used, clippy::unreadable_literal)]
    #[tokio::test]
    async fn test_fav_resource_list() {
        let core = BiliCore::default();
        let res = core.fav_resource_list(66458634, None, None).await;

        println!("{res:?}");
        assert!(res.is_ok());

        let res = res.unwrap();
        println!("{res:?}");
    }
}
