//! Endpoints that expose metadata about crate versions
//!
//! These endpoints provide data that could be obtained directly from the
//! index or cached metadata which was extracted (client side) from the
//! `Cargo.toml` file.

use crate::app::AppState;
use crate::models::VersionOwnerAction;
use crate::util::errors::AppResult;
use crate::views::EncodableVersion;
use axum::Json;
use serde::Serialize;

use super::CrateVersionPath;

/// Response returned when getting crate version metadata.
#[derive(Debug, Serialize, utoipa::ToSchema)]
pub struct VersionGetResponse {
    pub version: EncodableVersion,
}

/// Get crate version metadata.
#[utoipa::path(
    get,
    path = "/api/v1/crates/{name}/{version}",
    params(CrateVersionPath),
    tag = "versions",
    responses(
        (status = 200, description = "Successful Response", body = inline(VersionGetResponse)),
        (status = "4XX", description = "Client Error", body = crate::util::errors::ApiErrorResponse<'_>),
        (status = "5XX", description = "Server Error", body = crate::util::errors::ApiErrorResponse<'_>),
    ),
)]
pub async fn find_version(
    state: AppState,
    path: CrateVersionPath,
) -> AppResult<Json<VersionGetResponse>> {
    let conn = state.db_read().await?;
    let (version, krate) = path.load_version_and_crate(&conn).await?;
    let (actions, published_by) = tokio::try_join!(
        VersionOwnerAction::by_version(&conn, &version),
        version.published_by(&conn),
    )?;

    let version = EncodableVersion::from(version, &krate.name, published_by, actions);
    Ok(Json(VersionGetResponse { version }))
}
