use axum::{
Json,
extract::{Query, State},
http::StatusCode,
};
use fraiseql_core::db::traits::DatabaseAdapter;
use serde::{Deserialize, Serialize};
use crate::{
routes::graphql::AppState,
usage::aggregator::{UsageSummary, validate_period},
};
#[non_exhaustive]
#[derive(Debug, Deserialize)]
pub struct UsageQueryParams {
pub tenant_id: String,
pub period: String,
}
#[non_exhaustive]
#[derive(Debug, Serialize)]
pub struct UsageResponse {
pub tenant_id: String,
pub period: String,
pub usage: UsageSummary,
}
pub async fn usage_handler<A: DatabaseAdapter>(
State(state): State<AppState<A>>,
Query(params): Query<UsageQueryParams>,
) -> Result<Json<UsageResponse>, (StatusCode, Json<serde_json::Value>)> {
if !validate_period(¶ms.period) {
return Err((
StatusCode::BAD_REQUEST,
Json(serde_json::json!({"error": "invalid period format"})),
));
}
let usage = state.usage.query(¶ms.tenant_id, ¶ms.period);
Ok(Json(UsageResponse {
tenant_id: params.tenant_id,
period: params.period,
usage,
}))
}