// 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 std::sync::Arc;

use axum::{Json, Router, extract::State, http::Method, routing::get};
use http::header::AUTHORIZATION;
use openidconnect::{ClientId, ClientSecret, IssuerUrl};
use pib_service_api_types::config::api::ApiConfig;
use serde::{Deserialize, Serialize};
use tower_http::{
    auth::AsyncRequireAuthorizationLayer,
    cors::{AllowOrigin, CorsLayer},
};

use crate::{OidcAuth, ServiceState};

mod body;
mod me;

pub(super) fn router(service_state: ServiceState) -> Router {
    let cors = CorsLayer::new()
        .allow_methods([
            Method::GET,
            Method::POST,
            Method::PUT,
            Method::DELETE,
            Method::PATCH,
        ])
        .allow_headers([AUTHORIZATION])
        .allow_origin(AllowOrigin::mirror_request());
    let issuer_url = IssuerUrl::new(service_state.oidc.issuer.clone()).unwrap();
    let client_id = service_state.oidc.client_id.clone();
    let client_secret = service_state.oidc.client_secret.clone();
    let inventory_provider = service_state.inventory_provider.clone();
    let oidc = OidcAuth::new(
        issuer_url,
        ClientId::new(client_id),
        ClientSecret::new(client_secret),
        inventory_provider,
    );

    let public = Router::new()
        .route("/", get(index))
        .route("/config", get(config));
    let private = Router::new()
        .route("/me/profile", get(me::profile::get))
        .route("/body", get(body::get))
        .route("/body/{body_id}", get(body::by_body_id::get))
        .route(
            "/body/{body_id}/meeting",
            get(body::by_body_id::meeting::get).post(body::by_body_id::meeting::post),
        )
        .route(
            "/body/{body_id}/meeting/{meeting_id}",
            get(body::by_body_id::meeting::by_meeting_id::get),
        )
        .layer(AsyncRequireAuthorizationLayer::new(oidc));
    Router::new()
        .merge(public)
        .merge(private)
        .layer(cors)
        .with_state(Arc::new(service_state))
}

async fn config(State(service_state): State<Arc<ServiceState>>) -> Json<ApiConfig> {
    Json(ApiConfig {
        oidc: service_state.oidc.clone(),
    })
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
struct Index {}

async fn index() -> Json<Index> {
    Json(Index {})
}
