//! Staff management database queries.
//!
//! These queries are used by the owner interface and require the chattyness_owner role.

use sqlx::PgPool;
use uuid::Uuid;

use crate::models::{ServerRole, StaffMember};
use chattyness_error::AppError;

/// Get all staff members.
pub async fn get_all_staff(pool: &PgPool) -> Result<Vec<StaffMember>, AppError> {
    let staff = sqlx::query_as::<_, StaffMember>(
        r#"
        SELECT
            s.user_id,
            u.username,
            u.display_name,
            u.email,
            s.role,
            s.appointed_by,
            s.appointed_at
        FROM server.staff s
        JOIN auth.users u ON s.user_id = u.id
        ORDER BY
            CASE s.role
                WHEN 'owner' THEN 1
                WHEN 'admin' THEN 2
                WHEN 'moderator' THEN 3
            END,
            s.appointed_at DESC
        "#,
    )
    .fetch_all(pool)
    .await?;

    Ok(staff)
}

/// Get staff members by role.
pub async fn get_staff_by_role(
    pool: &PgPool,
    role: ServerRole,
) -> Result<Vec<StaffMember>, AppError> {
    let staff = sqlx::query_as::<_, StaffMember>(
        r#"
        SELECT
            s.user_id,
            u.username,
            u.display_name,
            u.email,
            s.role,
            s.appointed_by,
            s.appointed_at
        FROM server.staff s
        JOIN auth.users u ON s.user_id = u.id
        WHERE s.role = $1
        ORDER BY s.appointed_at DESC
        "#,
    )
    .bind(role)
    .fetch_all(pool)
    .await?;

    Ok(staff)
}

/// Create a staff member (promote existing user).
pub async fn create_staff(
    pool: &PgPool,
    user_id: Uuid,
    role: ServerRole,
    appointed_by: Option<Uuid>,
) -> Result<StaffMember, AppError> {
    let staff = sqlx::query_as::<_, StaffMember>(
        r#"
        WITH inserted AS (
            INSERT INTO server.staff (user_id, role, appointed_by)
            VALUES ($1, $2, $3)
            RETURNING user_id, role, appointed_by, appointed_at
        )
        SELECT
            i.user_id,
            u.username,
            u.display_name,
            u.email,
            i.role,
            i.appointed_by,
            i.appointed_at
        FROM inserted i
        JOIN auth.users u ON i.user_id = u.id
        "#,
    )
    .bind(user_id)
    .bind(role)
    .bind(appointed_by)
    .fetch_one(pool)
    .await?;

    Ok(staff)
}

/// Remove a staff member.
pub async fn delete_staff(pool: &PgPool, user_id: Uuid) -> Result<(), AppError> {
    sqlx::query("DELETE FROM server.staff WHERE user_id = $1")
        .bind(user_id)
        .execute(pool)
        .await?;

    Ok(())
}
