use axum::Json;
use axum::extract::{Path, Query, State};
use axum::http::StatusCode;
use serde::Deserialize;
use serde_json::{Value, json};
use super::stations::load;
use crate::calls;
use crate::error::AppError;
use crate::reservation::{self, ReserveRequest};
use crate::state::App;
pub async fn create(
State(app): State<App>,
Path(identity): Path<String>,
Json(req): Json<ReserveRequest>,
) -> Result<(StatusCode, Json<Value>), AppError> {
let version = calls::connected_version(&app, &identity).await?;
let station = load(&app, &identity).await?;
let (r, response) = reservation::reserve(&app, &station, version, &req).await?;
let code = if r.status == "Accepted" {
StatusCode::CREATED
} else {
StatusCode::OK
};
Ok((
code,
Json(json!({ "reservation": r, "response": response })),
))
}
#[derive(Debug, Deserialize)]
pub struct ListQuery {
pub active: Option<bool>,
pub limit: Option<i64>,
}
pub async fn list(
State(app): State<App>,
Path(identity): Path<String>,
Query(q): Query<ListQuery>,
) -> Result<Json<Value>, AppError> {
let station = load(&app, &identity).await?;
let list = crate::db::reservations::list(
&app.db,
station.id,
q.active.unwrap_or(false),
q.limit.unwrap_or(100).clamp(1, 1000),
)
.await?;
Ok(Json(json!(list)))
}
pub async fn get(
State(app): State<App>,
Path((identity, id)): Path<(String, i32)>,
) -> Result<Json<Value>, AppError> {
let station = load(&app, &identity).await?;
let r = crate::db::reservations::get(&app.db, station.id, id)
.await?
.ok_or_else(|| AppError::NotFound(format!("reservation {id} not found")))?;
Ok(Json(json!(r)))
}
pub async fn cancel(
State(app): State<App>,
Path((identity, id)): Path<(String, i32)>,
) -> Result<Json<Value>, AppError> {
let version = calls::connected_version(&app, &identity).await?;
let station = load(&app, &identity).await?;
let (r, response) = reservation::cancel(&app, &station, version, id).await?;
Ok(Json(json!({ "reservation": r, "response": response })))
}