use axum::Json; use axum::extract::{Path, State}; use api_types::{ ChannelResponse, ConfigSnapshotResponse, CreateChannelRequest, PatchSnapshotRequest, UpdateChannelRequest, }; use application::channels::{ CreateChannelCommand, DeleteChannelCommand, GetChannelQuery, ListByOwnerQuery, ListChannelsQuery, UpdateChannelCommand, }; use application::config_snapshots::{ GetSnapshotQuery, ListSnapshotsQuery, PatchLabelCommand, RestoreSnapshotCommand, SaveSnapshotCommand, }; use domain::DomainError; use crate::errors::AppError; use crate::extractors::CurrentUser; use crate::state::AppState; pub async fn list_channels( State(state): State, CurrentUser(_user): CurrentUser, ) -> Result>, AppError> { let channels = application::channels::list::execute(&state.channel_query_deps, ListChannelsQuery).await?; Ok(Json(channels.into_iter().map(ChannelResponse::from).collect())) } pub async fn list_my_channels( State(state): State, CurrentUser(user): CurrentUser, ) -> Result>, AppError> { let query = ListByOwnerQuery { owner_id: user.id(), }; let channels = application::channels::list_by_owner::execute(&state.channel_query_deps, query).await?; Ok(Json(channels.into_iter().map(ChannelResponse::from).collect())) } pub async fn create_channel( State(state): State, CurrentUser(user): CurrentUser, Json(req): Json, ) -> Result, AppError> { let cmd = CreateChannelCommand { owner_id: user.id(), name: req.name, timezone: req.timezone, }; let channel = application::channels::create::execute(&state.channel_command_deps, cmd).await?; Ok(Json(ChannelResponse::from(channel))) } pub async fn get_channel( State(state): State, CurrentUser(_user): CurrentUser, Path(id): Path, ) -> Result, AppError> { let query = GetChannelQuery { channel_id: id.into(), }; let channel = application::channels::get::execute(&state.channel_query_deps, query) .await? .ok_or_else(|| AppError(DomainError::NotFound(format!("Channel {id} not found"))))?; Ok(Json(ChannelResponse::from(channel))) } pub async fn update_channel( State(state): State, CurrentUser(user): CurrentUser, Path(id): Path, Json(req): Json, ) -> Result, AppError> { let cmd = UpdateChannelCommand { channel_id: id.into(), owner_id: user.id(), name: req.name, description: req.description.map(Some), timezone: req.timezone, schedule_config: req.schedule_config.map(Into::into), recycle_policy: req.recycle_policy, auto_schedule: req.auto_schedule, }; let channel = application::channels::update::execute(&state.channel_command_deps, cmd).await?; Ok(Json(ChannelResponse::from(channel))) } pub async fn delete_channel( State(state): State, CurrentUser(user): CurrentUser, Path(id): Path, ) -> Result { let cmd = DeleteChannelCommand { channel_id: id.into(), owner_id: user.id(), }; application::channels::delete::execute(&state.channel_command_deps, cmd).await?; Ok(axum::http::StatusCode::NO_CONTENT) } pub async fn save_snapshot( State(state): State, CurrentUser(_user): CurrentUser, Path(id): Path, ) -> Result, AppError> { let cmd = SaveSnapshotCommand { channel_id: id.into(), label: None, }; let snap = application::config_snapshots::save::execute(&state.config_snapshot_deps, cmd).await?; Ok(Json(ConfigSnapshotResponse::from(snap))) } pub async fn list_snapshots( State(state): State, CurrentUser(_user): CurrentUser, Path(id): Path, ) -> Result>, AppError> { let query = ListSnapshotsQuery { channel_id: id.into(), }; let snaps = application::config_snapshots::list::execute(&state.config_snapshot_deps, query).await?; Ok(Json(snaps.into_iter().map(ConfigSnapshotResponse::from).collect())) } pub async fn get_snapshot( State(state): State, CurrentUser(_user): CurrentUser, Path((id, snapshot_id)): Path<(uuid::Uuid, uuid::Uuid)>, ) -> Result, AppError> { let query = GetSnapshotQuery { channel_id: id.into(), snapshot_id: snapshot_id.into(), }; let snap = application::config_snapshots::get::execute(&state.config_snapshot_deps, query) .await? .ok_or_else(|| AppError(DomainError::NotFound("Snapshot not found".into())))?; Ok(Json(ConfigSnapshotResponse::from(snap))) } pub async fn patch_snapshot( State(state): State, CurrentUser(_user): CurrentUser, Path((id, snapshot_id)): Path<(uuid::Uuid, uuid::Uuid)>, Json(req): Json, ) -> Result, AppError> { let cmd = PatchLabelCommand { channel_id: id.into(), snapshot_id: snapshot_id.into(), label: req.label, }; let snap = application::config_snapshots::patch_label::execute(&state.config_snapshot_deps, cmd) .await? .ok_or_else(|| AppError(DomainError::NotFound("Snapshot not found".into())))?; Ok(Json(ConfigSnapshotResponse::from(snap))) } pub async fn restore_snapshot( State(state): State, CurrentUser(_user): CurrentUser, Path((id, snapshot_id)): Path<(uuid::Uuid, uuid::Uuid)>, ) -> Result, AppError> { let cmd = RestoreSnapshotCommand { channel_id: id.into(), snapshot_id: snapshot_id.into(), }; let channel = application::config_snapshots::restore::execute(&state.config_snapshot_deps, cmd).await?; Ok(Json(ChannelResponse::from(channel))) }