//! Scene and Spot API handlers for user UI (READ-ONLY).

use axum::{
    Json,
    extract::{Path, State},
};
use sqlx::PgPool;
use uuid::Uuid;

use chattyness_db::{
    models::{Scene, SceneSummary, Spot, SpotSummary},
    queries::{realms, scenes, spots},
};
use chattyness_error::AppError;

/// Get the entry scene for a realm.
///
/// GET /api/realms/{slug}/entry-scene
///
/// Returns the realm's default/entry scene. This endpoint is public.
pub async fn get_entry_scene(
    State(pool): State<PgPool>,
    Path(slug): Path<String>,
) -> Result<Json<Scene>, AppError> {
    let realm = realms::get_realm_by_slug(&pool, &slug)
        .await?
        .ok_or_else(|| AppError::NotFound(format!("Realm '{}' not found", slug)))?;

    let scene = scenes::get_entry_scene_for_realm(&pool, realm.id, realm.default_scene_id)
        .await?
        .ok_or_else(|| AppError::NotFound("No entry scene found for this realm".to_string()))?;

    Ok(Json(scene))
}

/// List scenes for a realm.
pub async fn list_scenes(
    State(pool): State<PgPool>,
    Path(slug): Path<String>,
) -> Result<Json<Vec<SceneSummary>>, AppError> {
    let realm = realms::get_realm_by_slug(&pool, &slug)
        .await?
        .ok_or_else(|| AppError::NotFound(format!("Realm '{}' not found", slug)))?;

    let scene_list = scenes::list_scenes_for_realm(&pool, realm.id).await?;
    Ok(Json(scene_list))
}

/// Get a scene by slug.
pub async fn get_scene(
    State(pool): State<PgPool>,
    Path((slug, scene_slug)): Path<(String, String)>,
) -> Result<Json<Scene>, AppError> {
    let realm = realms::get_realm_by_slug(&pool, &slug)
        .await?
        .ok_or_else(|| AppError::NotFound(format!("Realm '{}' not found", slug)))?;

    let scene = scenes::get_scene_by_slug(&pool, realm.id, &scene_slug)
        .await?
        .ok_or_else(|| AppError::NotFound(format!("Scene '{}' not found", scene_slug)))?;

    Ok(Json(scene))
}

/// List spots for a scene.
pub async fn list_spots(
    State(pool): State<PgPool>,
    Path((slug, scene_slug)): Path<(String, String)>,
) -> Result<Json<Vec<SpotSummary>>, AppError> {
    let realm = realms::get_realm_by_slug(&pool, &slug)
        .await?
        .ok_or_else(|| AppError::NotFound(format!("Realm '{}' not found", slug)))?;

    let scene = scenes::get_scene_by_slug(&pool, realm.id, &scene_slug)
        .await?
        .ok_or_else(|| AppError::NotFound(format!("Scene '{}' not found", scene_slug)))?;

    let spot_list = spots::list_spots_for_scene(&pool, scene.id).await?;
    Ok(Json(spot_list))
}

/// Get a spot by ID.
pub async fn get_spot(
    State(pool): State<PgPool>,
    Path((_slug, _scene_slug, spot_id)): Path<(String, String, Uuid)>,
) -> Result<Json<Spot>, AppError> {
    let spot = spots::get_spot_by_id(&pool, spot_id)
        .await?
        .ok_or_else(|| AppError::NotFound("Spot not found".to_string()))?;

    Ok(Json(spot))
}
