/*
 * asklyphe-frontend routes/announcement.rs
 * - http routes for announcements
 *
 * 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 std::sync::Arc;
use askama::Template;
use asklyphe_common::nats::authservice::{AuthServiceQuery, AuthServiceRequest, AuthServiceResponse};
use asklyphe_common::nats::authservice::announcements::{AnnouncementFullRequest, AnnouncementFullResponse, LatestAnnouncementRequest, LatestAnnouncementResponse};
use asklyphe_common::nats::comms;
use asklyphe_common::nats::comms::ServiceResponse;
use async_nats::jetstream;
use axum::Extension;
use axum::extract::Path;
use axum::http::StatusCode;
use axum::response::IntoResponse;
use serde::Serialize;
use tracing::{debug, error};
use tracing::log::warn;
use crate::{Opts, ALPHA, BUILT_ON, GIT_COMMIT, VERSION, YEAR};
use crate::routes::index::FrontpageAnnouncement;
use crate::routes::Themes;

#[derive(Serialize, Debug)]
struct FullAnnouncement {
    title: String,
    date: String,
    creator: String,
    full: String
}

async fn announcement(nats: Arc<jetstream::Context>, slug: String) -> Option<FullAnnouncement> {
    let response = comms::query_service(
        comms::Query::AuthService(AuthServiceQuery {
            request: AuthServiceRequest::AnnouncementFullRequest(AnnouncementFullRequest { slug }),
            replyto: "".to_string(),
        }),
        &nats,
        false,
    ).await;
    if let Err(e) = response {
        error!("nats error: {:?}", e);
        None
    } else {
        let response = response.unwrap();
        match response {
            ServiceResponse::SearchService(_) => {
                error!("sent search service response when asking for auth service!! investigate ASAP!!!");
                None
            }
            ServiceResponse::BingService(_) => {
                error!("sent bing service response when asking for auth service!! investigate ASAP!!!");
                None
            }
            ServiceResponse::AuthService(r) => match r {
                AuthServiceResponse::AnnouncementFullResponse(v) => {
                    match v {
                        AnnouncementFullResponse::Some(v) => {
                            Some(FullAnnouncement {
                                title: v.title,
                                date: chrono::DateTime::from_timestamp(v.created_on, 0).unwrap().to_rfc2822(),
                                creator: v.creator,
                                full: v.markdown_text.replace("\n", "<br/>"),
                            })
                        }
                        AnnouncementFullResponse::NotFound => {
                            None
                        }
                        AnnouncementFullResponse::InternalServerError(e) => {
                            warn!("internal server error while getting announcement: {}", e);
                            None
                        }
                    }
                }
                x => {
                    error!("auth service gave {} to our user info request!", x);
                    None
                }
            },
        }
    }
}

#[derive(Template)]
#[template(path = "announcement.html")]
pub struct AnnouncementTemplate {
    version: String,
    git_commit: String,
    built_on: String,
    year: String,
    alpha: bool,
    theme: Themes,
    announcement: FullAnnouncement,
}

pub async fn announcement_full(Extension(nats): Extension<Arc<jetstream::Context>>, Extension(opts): Extension<Opts>, Path(slug): Path<String>) -> impl IntoResponse {
    debug!("looking up {slug}");
    if let Some(announcement) = announcement(nats.clone(), slug.clone()).await {
        AnnouncementTemplate {
            version: VERSION.to_string(),
            git_commit: GIT_COMMIT.to_string(),
            built_on: BUILT_ON.to_string(),
            year: YEAR.to_string(),
            alpha: ALPHA,
            theme: Themes::Default,
            announcement,
        }.into_response()
    } else {
        StatusCode::NOT_FOUND.into_response()
    }
}
