/*
 * asklyphe-common nats/authservice/admin.rs
 * - nats structs for admin-only queries
 *
 * Copyright (C) 2025 Real Microsoft, LLC
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

use serde::{Deserialize, Serialize};
use crate::nats::authservice::UserPrivateToken;

/// # StatsRequest
/// sent from frontend -> authsrvc, requires token with admin privs, returns data for display
/// on the admin stats summary page
/// expecting an AuthServiceResponse::StatsResponse back
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StatsRequest {
    pub token: UserPrivateToken,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Stats {
    pub last_ten_users: Vec<String>,
    pub user_count: usize,
    pub admin_count: usize,
    pub active_verification_requests: usize,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum StatsResponse {
    Success(Stats),
    InternalServerError(String),
    Logout,
    AccessDenied,
}

/// # AdminInviteCodeGenerateRequest
/// sent from frontend -> authsrvc, requires token with admin privs
/// adds a valid invite code to the database
/// expecting an AuthServiceResponse::AdminInviteCodeGenerateResponse back
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdminInviteCodeGenerateRequest {
    pub token: UserPrivateToken,
    pub invite_code: String,
    pub comment: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AdminInviteCodeGenerateResponse {
    Success,
    CodeAlreadyExists,
    InternalServerError(String),
    Logout,
    AccessDenied,
}

/// # AdminListInviteCodesRequest
/// sent from frontend -> authsrvc, requires token with admin privs
/// lists invite codes that match the criteria
/// expecting an AuthServiceResponse::AdminListInviteCodesResponse back
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdminListInviteCodesRequest {
    pub token: UserPrivateToken,
    /// if true, will return invite codes that have been used instead of ones that are not yet used
    pub show_used: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InviteCodeSerialized {
    pub code: String,
    pub comment: String,
    pub creator: String,
    pub root_creator: String,
    pub created_at: String,
    pub used_at: Option<String>,
    pub used_by: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AdminListInviteCodesResponse {
    Success(Vec<InviteCodeSerialized>),
    InternalServerError(String),
    Logout,
    AccessDenied,
}

/// # AdminCreateAnnouncementRequest
/// sent from frontend -> authsrvc, requires token with admin privs
/// creates an announcement, and optionally sends emails to those who want to receive them
/// expecting an AuthServiceResponse::AdminCreateAnnouncementRequest
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdminCreateAnnouncementRequest {
    pub token: UserPrivateToken,
    pub title: String,
    pub slug: String,
    pub short_text: String,
    pub full_markdown_text: String,
    pub send_emails: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AdminCreateAnnouncementResponse {
    Success,
    SlugTaken,
    InternalServerError(String),
    Logout,
    AccessDenied,
}

/// # AdminUpdateAnnouncementRequest
/// sent from frontend -> authsrvc, requires token with admin privs
/// updates the contents of an announcement
/// expecting an AuthServiceResponse::AdminUpdateAnnouncementRequest
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdminUpdateAnnouncementRequest {
    pub token: UserPrivateToken,
    pub slug: String,
    pub new_title: String,
    pub new_short_text: String,
    pub new_full_markdown_text: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AdminUpdateAnnouncementResponse {
    Success,
    OriginalNotFound,
    InternalServerError(String),
    Logout,
    AccessDenied,
}

/// # AdminListAllUsersRequest
/// sent from frontend -> authsrvc, requires token with admin privs
/// returns a list of all users with accounts
/// expecting an AuthServiceResponse::AdminListAllUsersResponse
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdminListAllUsersRequest {
    pub token: UserPrivateToken,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserSerialized {
    pub username: String,
    pub email: String,
    pub verified: bool,
    pub admin: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AdminListAllUsersResponse {
    Success(Vec<UserSerialized>),
    InternalServerError(String),
    Logout,
    AccessDenied,
}