//! User management API handlers.

use axum::{
    extract::{Path, Query, State},
    Json,
};
use chattyness_db::{
    models::{
        AccountStatus, CreateUserRequest, RealmRole, RealmSummary, UserDetail, UserListItem,
        UserRealmMembership,
    },
    queries::owner as queries,
};
use chattyness_error::AppError;
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use uuid::Uuid;

/// Response for user creation.
#[derive(Debug, Serialize)]
pub struct CreateUserResponse {
    pub id: Uuid,
    pub username: String,
    pub temporary_password: String,
}

/// Response for password reset.
#[derive(Debug, Serialize)]
pub struct PasswordResetResponse {
    pub user_id: Uuid,
    pub temporary_password: String,
}

/// Query parameters for user list.
#[derive(Debug, Deserialize)]
pub struct ListUsersQuery {
    pub limit: Option<i64>,
    pub offset: Option<i64>,
}

/// Query parameters for user search.
#[derive(Debug, Deserialize)]
pub struct SearchUsersQuery {
    pub q: String,
    pub limit: Option<i64>,
}

/// List all users with pagination.
pub async fn list_users(
    State(pool): State<PgPool>,
    Query(query): Query<ListUsersQuery>,
) -> Result<Json<Vec<UserListItem>>, AppError> {
    let limit = query.limit.unwrap_or(25).min(100);
    let offset = query.offset.unwrap_or(0);
    let users = queries::list_users(&pool, limit, offset).await?;
    Ok(Json(users))
}

/// Create a new user (optionally with staff role).
pub async fn create_user(
    State(pool): State<PgPool>,
    Json(req): Json<CreateUserRequest>,
) -> Result<Json<CreateUserResponse>, AppError> {
    req.validate()?;
    let (user_id, temporary_password) = queries::create_user_with_staff(&pool, &req).await?;
    Ok(Json(CreateUserResponse {
        id: user_id,
        username: req.username,
        temporary_password,
    }))
}

/// Reset user's password to a random token.
pub async fn reset_password(
    State(pool): State<PgPool>,
    Path(user_id): Path<Uuid>,
) -> Result<Json<PasswordResetResponse>, AppError> {
    let temporary_password = queries::reset_user_password(&pool, user_id).await?;
    Ok(Json(PasswordResetResponse {
        user_id,
        temporary_password,
    }))
}

/// Search users by username, email, or display name.
pub async fn search_users(
    State(pool): State<PgPool>,
    Query(query): Query<SearchUsersQuery>,
) -> Result<Json<Vec<UserListItem>>, AppError> {
    let limit = query.limit.unwrap_or(10).min(50);
    let users = queries::search_users(&pool, &query.q, limit).await?;
    Ok(Json(users))
}

/// Get user detail by ID.
pub async fn get_user(
    State(pool): State<PgPool>,
    Path(user_id): Path<Uuid>,
) -> Result<Json<UserDetail>, AppError> {
    let user = queries::get_user_detail(&pool, user_id).await?;
    Ok(Json(user))
}

/// Update status request.
#[derive(Debug, Deserialize)]
pub struct UpdateStatusRequest {
    pub status: AccountStatus,
}

/// Update user's account status.
pub async fn update_status(
    State(pool): State<PgPool>,
    Path(user_id): Path<Uuid>,
    Json(req): Json<UpdateStatusRequest>,
) -> Result<Json<UserDetail>, AppError> {
    let user = queries::update_user_status(&pool, user_id, req.status).await?;
    Ok(Json(user))
}

/// Get user's realm memberships.
pub async fn get_user_realms(
    State(pool): State<PgPool>,
    Path(user_id): Path<Uuid>,
) -> Result<Json<Vec<UserRealmMembership>>, AppError> {
    let memberships = queries::get_user_realms(&pool, user_id).await?;
    Ok(Json(memberships))
}

/// Add to realm request.
#[derive(Debug, Deserialize)]
pub struct AddToRealmRequestBody {
    pub realm_id: Uuid,
    pub role: RealmRole,
}

/// Add user to a realm.
pub async fn add_to_realm(
    State(pool): State<PgPool>,
    Path(user_id): Path<Uuid>,
    Json(req): Json<AddToRealmRequestBody>,
) -> Result<Json<()>, AppError> {
    queries::add_user_to_realm(&pool, user_id, req.realm_id, req.role).await?;
    Ok(Json(()))
}

/// Remove user from a realm.
pub async fn remove_from_realm(
    State(pool): State<PgPool>,
    Path((user_id, realm_id)): Path<(Uuid, Uuid)>,
) -> Result<Json<()>, AppError> {
    queries::remove_user_from_realm(&pool, user_id, realm_id).await?;
    Ok(Json(()))
}

/// List all realms (for dropdown).
pub async fn list_realms(
    State(pool): State<PgPool>,
) -> Result<Json<Vec<RealmSummary>>, AppError> {
    let realms = queries::list_all_realms(&pool).await?;
    Ok(Json(realms))
}
