// SPDX-FileCopyrightText: Politik im Blick developers
// SPDX-FileCopyrightText: Wolfgang Silbermayr <wolfgang@silbermayr.at>
//
// SPDX-License-Identifier: AGPL-3.0-or-later OR EUPL-1.2

#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Pagination {
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub total_elements: Option<usize>,

    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub elements_per_page: Option<usize>,

    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub current_page: Option<usize>,

    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub total_pages: Option<usize>,

    #[serde(default, flatten)]
    pub extensions: serde_json::Map<String, serde_json::Value>,
}

#[cfg(test)]
mod serde_tests {
    use pretty_assertions::assert_eq;
    use serde_json::json;

    use super::Pagination;

    fn example_pagination() -> Pagination {
        Pagination {
            total_elements: Some(50000),
            elements_per_page: Some(100),
            current_page: Some(3),
            total_pages: Some(500),
            extensions: serde_json::Map::new(),
        }
    }

    fn example_pagination_json() -> serde_json::Value {
        json!({
        "totalElements": 50000,
        "elementsPerPage": 100,
        "currentPage": 3,
        "totalPages":500})
    }

    #[test]
    fn serialize() {
        assert_eq!(json!(example_pagination()), example_pagination_json());
    }

    #[test]
    fn deserialize_good() {
        let deserialized: Pagination = serde_json::from_value(example_pagination_json())
            .expect("value must be deserializable as Pagination");
        assert_eq!(deserialized, example_pagination());
    }

    #[test]
    fn serialize_empty() {
        assert_eq!(
            json!(Pagination {
                total_elements: None,
                elements_per_page: None,
                current_page: None,
                total_pages: None,
                extensions: serde_json::Map::new(),
            }),
            json!({}),
        );
    }

    #[test]
    fn deserialize_empty() {
        let deserialized: Pagination =
            serde_json::from_value(json!({})).expect("value must be deserializable as Pagination");
        assert_eq!(
            deserialized,
            Pagination {
                total_elements: None,
                elements_per_page: None,
                current_page: None,
                total_pages: None,
                extensions: serde_json::Map::new(),
            }
        );
    }

    #[test]
    fn deserialize_bad() {
        assert!(serde_json::from_value::<Pagination>(json!("xyzabcd")).is_err());
        assert!(serde_json::from_value::<Pagination>(json!(true)).is_err());
        assert!(serde_json::from_value::<Pagination>(json!(123)).is_err());
    }
}
