//! Realm management API handlers.

use axum::{
    extract::{Path, Query, State},
    Json,
};
use chattyness_db::{
    models::{OwnerCreateRealmRequest, RealmDetail, RealmListItem, UpdateRealmRequest},
    queries::owner as queries,
};
use chattyness_error::AppError;
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use uuid::Uuid;

/// Create realm response.
#[derive(Debug, Serialize)]
pub struct CreateRealmResponse {
    pub realm_id: Uuid,
    pub slug: String,
    pub owner_id: Uuid,
    pub owner_temporary_password: Option<String>,
}

/// Transfer ownership request.
#[derive(Debug, Deserialize)]
pub struct TransferOwnershipRequest {
    pub new_owner_id: Uuid,
}

/// List query params.
#[derive(Debug, Deserialize)]
pub struct ListRealmsQuery {
    pub q: Option<String>,
    pub limit: Option<i64>,
    pub offset: Option<i64>,
}

/// List realms with optional search.
pub async fn list_realms(
    State(pool): State<PgPool>,
    Query(query): Query<ListRealmsQuery>,
) -> Result<Json<Vec<RealmListItem>>, AppError> {
    let limit = query.limit.unwrap_or(25).min(100);
    let offset = query.offset.unwrap_or(0);

    let realms = if let Some(ref q) = query.q {
        queries::search_realms(&pool, q, limit).await?
    } else {
        queries::list_realms_with_owner(&pool, limit, offset).await?
    };

    Ok(Json(realms))
}

/// Get a realm by slug.
pub async fn get_realm(
    State(pool): State<PgPool>,
    Path(slug): Path<String>,
) -> Result<Json<RealmDetail>, AppError> {
    let realm = queries::get_realm_by_slug(&pool, &slug).await?;
    Ok(Json(realm))
}

/// Create a new realm.
pub async fn create_realm(
    State(pool): State<PgPool>,
    Json(req): Json<OwnerCreateRealmRequest>,
) -> Result<Json<CreateRealmResponse>, AppError> {
    req.validate()?;

    // If owner_id is provided, create realm with existing user
    if let Some(owner_id) = req.owner_id {
        let realm_id = queries::create_realm(
            &pool,
            owner_id,
            &req.name,
            &req.slug,
            req.description.as_deref(),
            req.tagline.as_deref(),
            req.privacy,
            req.is_nsfw,
            req.max_users,
            req.allow_guest_access,
            req.theme_color.as_deref(),
        )
        .await?;

        Ok(Json(CreateRealmResponse {
            realm_id,
            slug: req.slug,
            owner_id,
            owner_temporary_password: None,
        }))
    } else {
        // Create realm with new user as owner
        let (realm_id, user_id, temporary_password) =
            queries::create_realm_with_new_owner(&pool, &req).await?;

        Ok(Json(CreateRealmResponse {
            realm_id,
            slug: req.slug,
            owner_id: user_id,
            owner_temporary_password: Some(temporary_password),
        }))
    }
}

/// Update a realm.
pub async fn update_realm(
    State(pool): State<PgPool>,
    Path(slug): Path<String>,
    Json(req): Json<UpdateRealmRequest>,
) -> Result<Json<RealmDetail>, AppError> {
    req.validate()?;

    // First get the realm to find its ID
    let existing = queries::get_realm_by_slug(&pool, &slug).await?;
    let realm = queries::update_realm(&pool, existing.id, &req).await?;
    Ok(Json(realm))
}

/// Transfer realm ownership.
pub async fn transfer_ownership(
    State(pool): State<PgPool>,
    Path(slug): Path<String>,
    Json(req): Json<TransferOwnershipRequest>,
) -> Result<Json<()>, AppError> {
    // First get the realm to find its ID
    let existing = queries::get_realm_by_slug(&pool, &slug).await?;
    queries::transfer_realm_ownership(&pool, existing.id, req.new_owner_id).await?;
    Ok(Json(()))
}
