//! Realm API handlers for user UI (READ-ONLY).

use axum::{
    extract::{Path, Query, State},
    Json,
};
use serde::{Deserialize, Serialize};
use sqlx::PgPool;

use chattyness_db::{
    models::{RealmSummary, RealmWithUserRole},
    queries::{memberships, realms},
};
use chattyness_error::AppError;

use crate::auth::OptionalAuthUser;

/// List query params.
#[derive(Debug, Deserialize)]
pub struct ListParams {
    pub include_nsfw: Option<bool>,
    pub page: Option<i64>,
    pub limit: Option<i64>,
}

/// List response.
#[derive(Debug, Serialize)]
pub struct ListResponse {
    pub realms: Vec<RealmSummary>,
}

/// List public realms.
pub async fn list_realms(
    State(pool): State<PgPool>,
    Query(params): Query<ListParams>,
) -> Result<Json<ListResponse>, AppError> {
    let limit = params.limit.unwrap_or(20).min(100);
    let offset = params.page.unwrap_or(0) * limit;
    let include_nsfw = params.include_nsfw.unwrap_or(false);

    let realm_list = realms::list_public_realms(&pool, include_nsfw, limit, offset).await?;

    Ok(Json(ListResponse { realms: realm_list }))
}

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

    // Get the user's role if authenticated
    let user_role = if let Some(user) = maybe_user {
        let membership = memberships::get_user_membership(&pool, user.id, realm.id).await?;
        membership.map(|m| m.role)
    } else {
        None
    };

    Ok(Json(RealmWithUserRole { realm, user_role }))
}

/// Check slug availability response.
#[derive(Debug, Serialize)]
pub struct SlugAvailableResponse {
    pub available: bool,
}

/// Check if a realm slug is available.
pub async fn check_slug_available(
    State(pool): State<PgPool>,
    Path(slug): Path<String>,
) -> Result<Json<SlugAvailableResponse>, AppError> {
    let available = realms::is_slug_available(&pool, &slug).await?;
    Ok(Json(SlugAvailableResponse { available }))
}
