/*
 * authservice process/mod.rs
 * - route incoming nats requests to their specific functions
 *
 * 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/>.
*/

mod basic_accounts;
mod profile;
mod admin;
mod announcements;

use asklyphe_common::nats::authservice::{AuthServiceQuery, AuthServiceRequest, AuthServiceResponse};
use sea_orm::DatabaseConnection;
use crate::process::admin::{admin_create_announcement, admin_invite_code_gen, admin_list_all_users, admin_list_invite_codes, admin_update_announcement, stats};
use crate::process::announcements::{announcement_full, announcement_list, latest_announcement};
use crate::process::basic_accounts::{cancel_email_change, email_change, login, logout, register_request, verify_email, verify_session};
use crate::process::profile::{change_theme, user_info};

pub async fn process(query: AuthServiceQuery, db: DatabaseConnection) -> AuthServiceResponse {
    // a future is used so that the whole program doesn't die if an algorithm panics
    // yes i know that's probably not the best way to do it, i'll fix it eventually
    let response = tokio::spawn(async move {
        match query.request {
            AuthServiceRequest::RegisterRequest(req) => {
                AuthServiceResponse::RegisterResponse(register_request(&db, req).await)
            }
            AuthServiceRequest::VerifyEmailRequest(req) => {
                AuthServiceResponse::VerifyEmailResponse(verify_email(&db, req).await)
            }
            AuthServiceRequest::LoginRequest(req) => {
                AuthServiceResponse::LoginResponse(login(&db, req).await)
            }
            AuthServiceRequest::AuthRequest(req) => {
                AuthServiceResponse::AuthResponse(verify_session(&db, req).await)
            }
            AuthServiceRequest::LogoutRequest(req) => {
                AuthServiceResponse::LogoutResponse(logout(&db, req).await)
            }
            AuthServiceRequest::UserInfoRequest(req) => {
                AuthServiceResponse::UserInfoResponse(user_info(&db, req).await)
            }
            AuthServiceRequest::EmailChangeRequest(req) => {
                AuthServiceResponse::EmailChangeResponse(email_change(&db, req).await)
            }
            AuthServiceRequest::CancelEmailChangeRequest(req) => {
                AuthServiceResponse::CancelEmailChangeResponse(cancel_email_change(&db, req).await)
            }
            AuthServiceRequest::ThemeChangeRequest(req) => {
                AuthServiceResponse::ThemeChangeResponse(change_theme(&db, req).await)
            }
            AuthServiceRequest::StatsRequest(req) => {
                AuthServiceResponse::StatsResponse(stats(&db, req).await)
            }
            AuthServiceRequest::AdminInviteCodeGenerateRequest(req) => {
                AuthServiceResponse::AdminInviteCodeGenerateResponse(admin_invite_code_gen(&db, req).await)
            }
            AuthServiceRequest::LatestAnnouncementRequest(req) => {
                AuthServiceResponse::LatestAnnouncementResponse(latest_announcement(&db, req).await)
            }
            AuthServiceRequest::AnnouncementListRequest(req) => {
                AuthServiceResponse::AnnouncementListResponse(announcement_list(&db, req).await)
            }
            AuthServiceRequest::AnnouncementFullRequest(req) => {
                AuthServiceResponse::AnnouncementFullResponse(announcement_full(&db, req).await)
            }
            AuthServiceRequest::AdminCreateAnnouncementRequest(req) => {
                AuthServiceResponse::AdminCreateAnnouncementResponse(admin_create_announcement(&db, req).await)
            }
            AuthServiceRequest::AdminUpdateAnnouncementRequest(req) => {
                AuthServiceResponse::AdminUpdateAnnouncementResponse(admin_update_announcement(&db, req).await)
            }
            AuthServiceRequest::AdminListInviteCodesRequest(req) => {
                AuthServiceResponse::AdminListInviteCodesResponse(admin_list_invite_codes(&db, req).await)
            }
            AuthServiceRequest::AdminListAllUsersRequest(req) => {
                AuthServiceResponse::AdminListAllUsersResponse(admin_list_all_users(&db, req).await)
            }
        }}).await;

    if let Ok(response) = response {
        response
    } else if let Err(e) = response {
        AuthServiceResponse::OtherError(e.to_string())
    } else {
        unreachable!()
    }
}