use axum::{ extract::{Path, State}, http::StatusCode, routing::{get, post}, Json, Router, }; use serde::{Deserialize, Serialize}; use crate::api::types::AppState; use crate::core::checkin; use crate::core::db::VideoStatus; #[derive(Debug, Serialize)] struct CheckinResponse { file_uuid: String, pre_chunks_moved: usize, speaker_detections_moved: usize, vectors_moved: usize, status: String, } #[derive(Debug, Serialize)] struct CheckoutResponse { file_uuid: String, rows_deleted: usize, status: String, } #[derive(Debug, Serialize)] struct WorkspaceStatusResponse { file_uuid: String, exists: bool, } async fn checkin_handler( State(state): State, Path(file_uuid): Path, ) -> Result, (StatusCode, Json)> { match checkin::checkin(&state.db, &file_uuid).await { Ok(result) => { if let Err(e) = state .db .update_video_status(&file_uuid, VideoStatus::Indexed) .await { tracing::warn!( "Failed to update video status to Indexed for {}: {}", file_uuid, e ); } Ok(Json(CheckinResponse { file_uuid: result.file_uuid.clone(), pre_chunks_moved: result.pre_chunks_moved, speaker_detections_moved: result.speaker_detections_moved, vectors_moved: result.vectors_moved, status: "indexed".to_string(), })) } Err(e) => Err(( StatusCode::INTERNAL_SERVER_ERROR, Json(serde_json::json!({ "error": format!("Checkin failed: {}", e), "file_uuid": file_uuid, })), )), } } async fn checkout_handler( State(state): State, Path(file_uuid): Path, ) -> Result, (StatusCode, Json)> { match checkin::checkout(&state.db, &file_uuid).await { Ok(result) => { if let Err(e) = state .db .update_video_status(&file_uuid, VideoStatus::CheckedOut) .await { tracing::warn!( "Failed to update video status to CheckedOut for {}: {}", file_uuid, e ); } Ok(Json(CheckoutResponse { file_uuid: result.file_uuid.clone(), rows_deleted: result.rows_deleted, status: "checked_out".to_string(), })) } Err(e) => Err(( StatusCode::INTERNAL_SERVER_ERROR, Json(serde_json::json!({ "error": format!("Checkout failed: {}", e), "file_uuid": file_uuid, })), )), } } async fn workspace_status_handler(Path(file_uuid): Path) -> Json { use crate::core::db::workspace_sqlite::WorkspaceDb; Json(WorkspaceStatusResponse { file_uuid: file_uuid.clone(), exists: WorkspaceDb::exists(&file_uuid), }) } pub fn checkin_routes() -> Router { Router::new() .route("/api/v1/file/:file_uuid/checkin", post(checkin_handler)) .route("/api/v1/file/:file_uuid/checkout", post(checkout_handler)) .route( "/api/v1/file/:file_uuid/workspace", get(workspace_status_handler), ) }