use axum::Json;
use axum::extract::{Path, Query, State};
use serde::Deserialize;
use uuid::Uuid;
use vti_common::error::AppError;
use vti_common::pagination::{Cursor, MAX_LIMIT, Paginated};
use crate::auth::AdminAuth;
use crate::join::{JoinRequest, JoinStatus, get_join_request, list_join_requests_paginated};
use crate::server::AppState;
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ListJoinRequestsQuery {
pub status: Option<JoinStatus>,
pub cursor: Option<String>,
pub limit: Option<usize>,
}
pub async fn list_join_requests(
_admin: AdminAuth,
State(state): State<AppState>,
Query(query): Query<ListJoinRequestsQuery>,
) -> Result<Json<Paginated<JoinRequest>>, AppError> {
let limit = query.limit.unwrap_or(50).clamp(1, MAX_LIMIT);
let audit_writer = state
.audit_writer
.as_ref()
.ok_or_else(|| AppError::Internal("audit_writer not initialised".into()))?;
let audit_key = audit_writer.active_key().await?;
let decoded_cursor = match &query.cursor {
Some(s) => Some(Cursor::decode(s, &audit_key.key)?),
None => None,
};
let mut page = list_join_requests_paginated(
&state.join_requests_ks,
&audit_key,
decoded_cursor.as_ref(),
limit,
)
.await?;
let filter_status = query.status.unwrap_or(JoinStatus::Pending);
page.items.retain(|r| r.status == filter_status);
Ok(Json(page))
}
pub async fn show_join_request(
_admin: AdminAuth,
State(state): State<AppState>,
Path(id): Path<Uuid>,
) -> Result<Json<JoinRequest>, AppError> {
let req = get_join_request(&state.join_requests_ks, id)
.await?
.ok_or_else(|| AppError::NotFound(format!("join request not found: {id}")))?;
Ok(Json(req))
}