//! Loose props management API handlers for admin UI.

use axum::Json;
use axum::extract::Path;
use chattyness_db::{models::LooseProp, queries::loose_props};
use chattyness_error::{AppError, OptionExt};
use serde::Deserialize;
use uuid::Uuid;

use crate::auth::AdminConn;

// =============================================================================
// API Types
// =============================================================================

/// Request to update loose prop scale.
#[derive(Debug, Deserialize)]
pub struct UpdateLoosePropScaleRequest {
    /// Scale factor (0.1 - 10.0).
    pub scale: f32,
}

// =============================================================================
// API Handlers
// =============================================================================

/// Get a loose prop by ID.
pub async fn get_loose_prop(
    admin_conn: AdminConn,
    Path(loose_prop_id): Path<Uuid>,
) -> Result<Json<LooseProp>, AppError> {
    let conn = admin_conn.0;
    let mut guard = conn.acquire().await;

    let prop = loose_props::get_loose_prop_by_id(&mut *guard, loose_prop_id)
        .await?
        .or_not_found("Loose prop (may have expired)")?;

    Ok(Json(prop))
}

/// Update loose prop scale.
///
/// Server admins can update any loose prop scale.
pub async fn update_loose_prop_scale(
    admin_conn: AdminConn,
    Path(loose_prop_id): Path<Uuid>,
    Json(req): Json<UpdateLoosePropScaleRequest>,
) -> Result<Json<LooseProp>, AppError> {
    let conn = admin_conn.0;
    let mut guard = conn.acquire().await;

    let prop = loose_props::update_loose_prop_scale(&mut *guard, loose_prop_id, req.scale).await?;

    tracing::info!(
        "Updated loose prop {} scale to {}",
        loose_prop_id,
        req.scale
    );

    Ok(Json(prop))
}

/// List loose props in a scene/channel.
pub async fn list_loose_props(
    admin_conn: AdminConn,
    Path(scene_id): Path<Uuid>,
) -> Result<Json<Vec<LooseProp>>, AppError> {
    let conn = admin_conn.0;
    let mut guard = conn.acquire().await;

    let props = loose_props::list_channel_loose_props(&mut *guard, scene_id).await?;

    Ok(Json(props))
}
