//! Event GraphQL queries
//!
//! Queries for the event audit trail system.

use async_graphql::{Context, Object, Result};
use uuid::Uuid;

use crate::db::Database;
use crate::graphql::types::EventType_;
use crate::models::Event;

#[derive(Default)]
pub struct EventQuery;

#[Object]
impl EventQuery {
    /// Get a single event by ID
    async fn event(&self, ctx: &Context<'_>, id: Uuid) -> Result<Option<EventType_>> {
        let db = ctx.data::<Database>()?;
        let pool = db.pool().await;

        let event = sqlx::query_as::<_, Event>(
            r#"
            SELECT id, event_type, entity_type, entity_id, actor_type, actor_id,
                   metadata, timestamp, created_at
            FROM events
            WHERE id = $1
            "#,
        )
        .bind(id)
        .fetch_optional(&*pool)
        .await?;

        Ok(event.map(EventType_::from))
    }

    /// Get events for an entity (audit trail)
    async fn events_for_entity(
        &self,
        ctx: &Context<'_>,
        entity_type: String,
        entity_id: Uuid,
        #[graphql(default = 50)] limit: i32,
        #[graphql(default = 0)] offset: i32,
    ) -> Result<Vec<EventType_>> {
        let db = ctx.data::<Database>()?;
        let pool = db.pool().await;

        let events: Vec<Event> = sqlx::query_as(
            r#"
            SELECT id, event_type, entity_type, entity_id, actor_type, actor_id,
                   metadata, timestamp, created_at
            FROM events
            WHERE entity_type = $1 AND entity_id = $2
            ORDER BY timestamp DESC, created_at DESC
            LIMIT $3 OFFSET $4
            "#,
        )
        .bind(&entity_type)
        .bind(entity_id)
        .bind(limit)
        .bind(offset)
        .fetch_all(&*pool)
        .await?;

        Ok(events.into_iter().map(EventType_::from).collect())
    }

    /// Get recent events across all entities (admin view)
    async fn recent_events(
        &self,
        ctx: &Context<'_>,
        #[graphql(default = 100)] limit: i32,
        #[graphql(default = 0)] offset: i32,
    ) -> Result<Vec<EventType_>> {
        let db = ctx.data::<Database>()?;
        let pool = db.pool().await;

        let events: Vec<Event> = sqlx::query_as(
            r#"
            SELECT id, event_type, entity_type, entity_id, actor_type, actor_id,
                   metadata, timestamp, created_at
            FROM events
            ORDER BY timestamp DESC, created_at DESC
            LIMIT $1 OFFSET $2
            "#,
        )
        .bind(limit)
        .bind(offset)
        .fetch_all(&*pool)
        .await?;

        Ok(events.into_iter().map(EventType_::from).collect())
    }

    /// Get events by actor (user activity history)
    async fn events_by_actor(
        &self,
        ctx: &Context<'_>,
        actor_type: String,
        actor_id: Uuid,
        #[graphql(default = 50)] limit: i32,
        #[graphql(default = 0)] offset: i32,
    ) -> Result<Vec<EventType_>> {
        let db = ctx.data::<Database>()?;
        let pool = db.pool().await;

        let events: Vec<Event> = sqlx::query_as(
            r#"
            SELECT id, event_type, entity_type, entity_id, actor_type, actor_id,
                   metadata, timestamp, created_at
            FROM events
            WHERE actor_type = $1 AND actor_id = $2
            ORDER BY timestamp DESC, created_at DESC
            LIMIT $3 OFFSET $4
            "#,
        )
        .bind(&actor_type)
        .bind(actor_id)
        .bind(limit)
        .bind(offset)
        .fetch_all(&*pool)
        .await?;

        Ok(events.into_iter().map(EventType_::from).collect())
    }
}
