// SPDX-FileCopyrightText: 2024 Bingwu Zhang <xtexchooser@duck.com>
// SPDX-License-Identifier: GPL-3.0-or-later
//! Generator for Special:RecentChanges
//!
//! See the [`RecentChanges`] type documentation for specifics.
use crate::generators::{Generator, ParamValue};
use crate::{Bot, Result};
use mwapi_responses::query;
use mwtimestamp::Timestamp;

#[query(
    list = "recentchanges",
    rcprop = "title|timestamp|ids|flags|loginfo|user|userid|tags|comment"
)]
pub struct RecentChangesResponse {}

#[derive(Clone, Debug)]
pub enum Order {
    Newer,
    Older,
}

impl ParamValue for Order {
    fn stringify(&self) -> String {
        match self {
            Self::Newer => "newer",
            Self::Older => "older",
        }
        .to_string()
    }
}

/// Get recent changes as shown in Special:RecentChanges.
///
/// See [API documentation](https://www.mediawiki.org/wiki/API:RecentChanges) for more details.
#[derive(Default, Debug, Generator)]
#[generator(
    return_type = "RecentChangesResponseItem",
    response_type = "RecentChangesResponse",
    transform_fn = "transform"
)]
#[params(list = "recentchanges", rclimit = "max")]
pub struct RecentChanges {
    #[param("rctype")]
    types: Option<Vec<String>>,
    #[param("rcstart")]
    start: Option<Timestamp>,
    #[param("rcend")]
    end: Option<Timestamp>,
    #[param("rcdir")]
    order: Option<Order>,
    #[param("rcnamespace")]
    namespace: Option<u32>,
    #[param("rcuser")]
    user: Option<String>,
    #[param("rcexcludeuser")]
    exclude_user: Option<String>,
    #[param("rctag")]
    tag: Option<String>,
    #[param("rcshow")]
    show: Option<Vec<String>>,
    #[param("rctoponly")]
    top_only: Option<bool>,
    #[param("rctitle")]
    title: Option<String>,
    #[param("rcslot")]
    slot: Option<String>,
}

fn transform(
    _bot: &Bot,
    item: RecentChangesResponseItem,
) -> Result<RecentChangesResponseItem> {
    // do nothing
    Ok(item)
}

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

    #[tokio::test]
    async fn test_recent_changes() {
        let bot = testwp().await;
        let gen = RecentChanges::new().start(Timestamp::now());

        let mut rcs = gen.generate(&bot);
        let mut count = 0;
        while let Some(item) = rcs.recv().await {
            dbg!(item.unwrap());

            if count >= 150 {
                break;
            }
            count += 1;
        }
        assert_eq!(count, 150);
    }
}
