use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
use uuid::Uuid;

#[derive(Debug, Serialize, Deserialize, FromRow)]
pub struct Role {
    pub id: Uuid,
    pub key: String,
    pub name: String,
    pub audience: String,
    pub is_active: bool,
    pub created_at: DateTime<Utc>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CreateRolePayload {
    pub key: String,
    pub name: String,
    pub audience: String,
}

pub struct RoleRepository;

impl RoleRepository {
    pub async fn create(
        pool: &sqlx::PgPool,
        payload: CreateRolePayload,
    ) -> Result<Role, sqlx::Error> {
        let role = sqlx::query_as::<_, Role>(
            r#"
            INSERT INTO roles (key, name, audience)
            VALUES ($1, $2, $3)
            RETURNING id, key, name, audience, is_active, created_at
            "#,
        )
        .bind(payload.key)
        .bind(payload.name)
        .bind(payload.audience)
        .fetch_one(pool)
        .await?;

        Ok(role)
    }

    pub async fn get_all(pool: &sqlx::PgPool) -> Result<Vec<Role>, sqlx::Error> {
        let roles = sqlx::query_as::<_, Role>(
            r#"
            SELECT id, key, name, audience, is_active, created_at
            FROM roles
            ORDER BY created_at DESC
            "#,
        )
        .fetch_all(pool)
        .await?;

        Ok(roles)
    }

    pub async fn get_by_key(pool: &sqlx::PgPool, key: &str) -> Result<Role, sqlx::Error> {
        let role = sqlx::query_as::<_, Role>(
            r#"
            SELECT id, key, name, audience, is_active, created_at
            FROM roles
            WHERE key = $1
            "#,
        )
        .bind(key)
        .fetch_one(pool)
        .await?;

        Ok(role)
    }
}
