// 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

use pib_service_api_auth::user::UserInfo;
use pib_service_api_permissions::{Method, Resource};
use pib_service_api_types::user::{User, get::ResponseBody};
use pib_service_inventory::Pagination;

use crate::{Backend, Result};

impl Backend {
    pub(crate) async fn user_get(
        &self,
        user: UserInfo,
        pagination: Pagination,
    ) -> Result<ResponseBody> {
        self.enforce_permissions(Resource::User, Method::GET, user.id)
            .await?;

        let mut inventory = self.inventory_provider.get_inventory().await?;

        let users = inventory.get_users(Some(pagination)).await?;

        let page = users.map(
            |pib_service_inventory::Item {
                 id,
                 created,
                 modified,
                 value:
                     pib_service_inventory::User {
                         sub,
                         display_name,
                         is_superuser,
                     },
             }| User {
                id,
                created,
                modified,
                sub,
                display_name,
                is_superuser,
            },
        );

        Ok(ResponseBody(page.into()))
    }
}

#[cfg(test)]
mod tests {
    use std::sync::Arc;

    use mockall::predicate::eq;
    use pib_service_api_auth::user::{Issuer, OidcSub, UserInfo};
    use pib_service_api_permissions::{Admission, Method, MockPermissions, Resource};
    use pib_service_api_types::config::oidc::OidcConfig;
    use pib_service_core_types::UserId;
    use pib_service_facade::{Service as _, paging::Pagination};
    use pib_service_test_utils::mock_inventory_with_provider;
    use pretty_assertions::assert_eq;

    use super::{ResponseBody, User};
    use crate::Backend;

    #[tokio::test]
    async fn endpoint() {
        let (inventory, provider) = mock_inventory_with_provider();
        let mut permissions = MockPermissions::new();
        let oidc = OidcConfig {
            issuer: "https://auth.example.com/".to_string(),
            client_id: "abcdef".to_string(),
            client_secret: "ghijkl".to_string(),
        };

        let user_id = UserId::from_u128(0x4444);
        let user_info = UserInfo {
            id: user_id,
            issuer: Issuer("https://auth.example.com".to_string()),
            sub: OidcSub("theuser".to_string()),
            display_name: Some("The User".to_string()),
            is_superuser: true,
        };

        let user_id_1 = UserId::from_u128(0x6666);
        let user_id_2 = UserId::from_u128(0x7777);

        permissions
            .expect_request_permission()
            .with(eq(Resource::User), eq(Method::GET), eq(user_id))
            .times(1)
            .return_once(|_, _, _| Ok(Admission::Allow));

        let user_1 = pib_service_inventory::Item {
            id: user_id_1,
            created: "2026-04-07T05:06:07+01:00".parse().unwrap(),
            modified: "2026-04-08T05:06:07+01:00".parse().unwrap(),
            value: pib_service_inventory::User {
                sub: "user_1".to_string(),
                display_name: None,
                is_superuser: true,
            },
        };

        let user_2 = pib_service_inventory::Item {
            id: user_id_2,
            created: "2026-04-07T05:06:07+01:00".parse().unwrap(),
            modified: "2026-04-08T05:06:07+01:00".parse().unwrap(),
            value: pib_service_inventory::User {
                sub: "user_2".to_string(),
                display_name: None,
                is_superuser: false,
            },
        };

        let raw = pib_service_inventory::DataPage {
            data: vec![user_1, user_2],
            pagination: pib_service_inventory::DataPagePagination {
                total_elements: 11,
                elements_per_page: 12,
                current_page: 13,
                total_pages: 14,
            },
        };

        inventory
            .write()
            .await
            .expect_get_users()
            .times(1)
            .return_once(move |_| Ok(raw));

        let backend = Backend::new(provider, Arc::new(permissions), oidc, None);

        let pagination = Pagination {
            page: 0.into(),
            per_page: 10.try_into().unwrap(),
        };

        let response = backend
            .handle_user_get(user_info, pagination)
            .await
            .unwrap();

        assert_eq!(
            response,
            ResponseBody(pib_service_core_types::DataPage {
                data: vec![
                    User {
                        id: user_id_1,
                        created: "2026-04-07T05:06:07+01:00".parse().unwrap(),
                        modified: "2026-04-08T05:06:07+01:00".parse().unwrap(),
                        sub: "user_1".to_string(),
                        display_name: None,
                        is_superuser: true,
                    },
                    User {
                        id: user_id_2,
                        created: "2026-04-07T05:06:07+01:00".parse().unwrap(),
                        modified: "2026-04-08T05:06:07+01:00".parse().unwrap(),
                        sub: "user_2".to_string(),
                        display_name: None,
                        is_superuser: false,
                    },
                ],
                pagination: pib_service_core_types::DataPagePagination {
                    total_elements: 11,
                    elements_per_page: 12,
                    current_page: 13,
                    total_pages: 14,
                }
            })
        );
    }
}
