// SPDX-FileCopyrightText: 2023 Misato Kano <me@mirror-kt.dev>
// SPDX-License-Identifier: GPL-3.0-or-later
//! Generators related to log events
//!
//! See the [`LogEvents`] type documentation for specifics.
use crate::generators::{Generator, ParamValue};
use crate::{Bot, Result};
use mwapi_responses::query;
use mwtimestamp::Timestamp;

#[query(
    list = "logevents",
    leprop = "ids|title|type|user|userid|timestamp|comment|details|tags"
)]
pub struct LogEventsResponse {}

#[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 all logged events as shown in Special:Log.
///
/// See [API documentation](https://www.mediawiki.org/wiki/API:Logevents) for more details.
#[derive(Default, Debug, Generator)]
#[generator(
    return_type = "LogEventsResponseItem",
    response_type = "LogEventsResponse",
    transform_fn = "transform"
)]
#[params(list = "logevents", lelimit = "max")]
pub struct LogEvents {
    #[param("letype")]
    types: Option<Vec<String>>,
    #[param("leaction")]
    action: Option<String>,
    #[param("lestart")]
    start: Option<Timestamp>,
    #[param("leend")]
    end: Option<Timestamp>,
    #[param("ledir")]
    order: Option<Order>,
    #[param("leuser")]
    user: Option<String>,
    #[param("letitle")]
    title: Option<String>,
    #[param("lenamespace")]
    namespace: Option<u32>,
    #[param("letag")]
    tag: Option<String>,
}

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

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

    #[ignore] // Failing, see T354039
    #[tokio::test]
    async fn test_log_events() {
        let bot = testwp().await;
        let gen = LogEvents::new();

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

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