use crate::app::AppState;
use crate::controllers::version::CrateVersionPath;
use crate::storage::StorageKey;
use crate::util::{RequestUtils, redirect};
use axum::Json;
use axum::response::{IntoResponse, Response};
use http::request::Parts;
use http::{HeaderValue, header};
use serde::Serialize;

#[derive(Debug, Serialize, utoipa::ToSchema)]
pub struct UrlResponse {
    /// The URL to the readme file.
    #[schema(example = "https://static.crates.io/readmes/serde/serde-1.0.0.html")]
    pub url: String,
}

/// Get the readme of a crate version.
#[utoipa::path(
    get,
    path = "/api/v1/crates/{name}/{version}/readme",
    params(CrateVersionPath),
    tag = "versions",
    responses(
        (status = 302, description = "Successful Response (default)", headers(("location" = String, description = "The URL to the readme file."))),
        (status = 200, description = "Successful Response (for `content-type: application/json`)", body = inline(UrlResponse)),
        (status = "4XX", description = "Client Error", body = crate::util::errors::ApiErrorResponse<'_>),
        (status = "5XX", description = "Server Error", body = crate::util::errors::ApiErrorResponse<'_>),
    ),
)]
pub async fn get_version_readme(app: AppState, path: CrateVersionPath, req: Parts) -> Response {
    let key = StorageKey::for_readme(&path.name, &path.version);
    let url = app.storage.location(&key);
    let response = if req.wants_json() {
        Json(UrlResponse { url }).into_response()
    } else {
        redirect(url)
    };

    // The response body depends on the `Accept` request header.
    (
        [(header::VARY, HeaderValue::from_static("accept"))],
        response,
    )
        .into_response()
}
