use axum::{
    Json, Router,
    extract::State,
    http::{self},
    routing::get,
};
use hyper_util::client::legacy::connect::Connect;
use ogcapi_types::common::{
    LandingPage, Link,
    link_rel::{DATA, SELF, SERVICE_DOC},
    media_type::{JSON, OPEN_API_JSON},
};

use crate::collections_proxy::CollectionsProxy;

#[derive(Debug, Clone, Default)]
pub struct OgcApiConfig {
    pub title: Option<String>,
    pub description: Option<String>,
    pub attribution: Option<String>,
}

#[derive(Debug, Clone)]
struct OgcApiState {
    config: OgcApiConfig,
}

/// Construct a [Router] for a simple OGC API service.
pub async fn routes<C: Connect + Clone + Send + Sync + 'static>(
    collections_proxy: CollectionsProxy<C>,
) -> Router {
    let config = OgcApiConfig {
        title: Some("OGC API Proxy".to_string()),
        ..Default::default()
    };
    let state = OgcApiState { config };
    Router::new()
        .route("/", get(root))
        .route("/api", get(api))
        .with_state(state)
        .nest_service("/collections", collections_proxy)
}

async fn root(State(state): State<OgcApiState>) -> Json<LandingPage> {
    Json(LandingPage {
        title: state.config.title,
        description: state.config.description,
        attribution: state.config.attribution,
        links: vec![
            Link::new("/", SELF).title("Landing Page").mediatype(JSON),
            Link::new("/api", SERVICE_DOC)
                .title("The Open API definition")
                .mediatype(OPEN_API_JSON),
            Link::new("/collections", DATA)
                .title("The Open API definition")
                .mediatype(JSON),
        ],
        ..Default::default()
    })
}

async fn api(State(_state): State<OgcApiState>) -> http::StatusCode {
    // TODO construct OpenApiSpec based on proxied collections.
    http::StatusCode::SERVICE_UNAVAILABLE
}
