//! Interactive API docs: a locally-vendored Swagger UI served at `/docs`,
//! pointed at the manifest-generated spec at `/openapi.json`. Because the docs
//! and the API share an origin, "Try it out" calls hit the live endpoints.
//!
//! The Swagger UI assets are embedded in the binary (offline, no CDN). They are
//! distributed under Apache-2.0; the upstream license banner is kept in the
//! `static/swagger/*.js` file.

use crate::state::AppState;
use axum::extract::State;
use axum::http::header;
use axum::response::{Html, IntoResponse, Response};
use axum::Json;
use serde_json::Value;

static SWAGGER_CSS: &str = include_str!("../static/swagger/swagger-ui.css");
static SWAGGER_JS: &str = include_str!("../static/swagger/swagger-ui-bundle.js");

const INDEX_HTML: &str = r#"<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>roundabout_orm — API docs</title>
  <link rel="stylesheet" href="/docs/swagger-ui.css">
</head>
<body>
  <div id="swagger-ui"></div>
  <script src="/docs/swagger-ui-bundle.js"></script>
  <script>
    window.onload = function () {
      window.ui = SwaggerUIBundle({
        url: '/openapi.json',
        dom_id: '#swagger-ui',
        presets: [SwaggerUIBundle.presets.apis],
        layout: 'BaseLayout'
      });
    };
  </script>
</body>
</html>
"#;

/// `GET /docs` — the Swagger UI shell.
pub async fn index() -> Html<&'static str> {
    Html(INDEX_HTML)
}

/// `GET /docs/swagger-ui.css`
pub async fn css() -> Response {
    ([(header::CONTENT_TYPE, "text/css; charset=utf-8")], SWAGGER_CSS).into_response()
}

/// `GET /docs/swagger-ui-bundle.js`
pub async fn js() -> Response {
    (
        [(header::CONTENT_TYPE, "application/javascript; charset=utf-8")],
        SWAGGER_JS,
    )
        .into_response()
}

/// `GET /openapi.json` — the manifest-generated spec built once at startup.
pub async fn openapi_json(State(state): State<AppState>) -> Json<Value> {
    Json((*state.openapi).clone())
}
