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

#[derive(Debug, Serialize, Deserialize, FromRow)]
pub struct ActivityLog {
    pub id: Uuid,
    pub actor_id: Uuid,
    pub actor_type: String,
    pub entity_id: Uuid,
    pub entity_type: String,
    pub action: String,
    pub metadata: Option<serde_json::Value>,
    pub ip_address: Option<String>,
    pub user_agent: Option<String>,
    pub created_at: DateTime<Utc>,
}

pub struct ActivityLogRepository;

impl ActivityLogRepository {
    pub async fn create(
        pool: &PgPool,
        actor_id: Uuid,
        actor_type: &str,
        entity_id: Uuid,
        entity_type: &str,
        action: &str,
        metadata: Option<serde_json::Value>,
    ) -> Result<ActivityLog, sqlx::Error> {
        sqlx::query_as::<_, ActivityLog>(
            r#"
            INSERT INTO activity_logs (actor_id, actor_type, entity_id, entity_type, action, metadata)
            VALUES ($1, $2, $3, $4, $5, $6)
            RETURNING id, actor_id, actor_type, entity_id, entity_type, action, metadata, ip_address, user_agent, created_at
            "#
        )
        .bind(actor_id)
        .bind(actor_type)
        .bind(entity_id)
        .bind(entity_type)
        .bind(action)
        .bind(metadata)
        .fetch_one(pool)
        .await
    }

    pub async fn list_for_entity(
        pool: &PgPool,
        entity_type: &str,
        entity_id: Uuid,
    ) -> Result<Vec<ActivityLog>, sqlx::Error> {
        sqlx::query_as::<_, ActivityLog>(
            r#"
            SELECT id, actor_id, actor_type, entity_id, entity_type, action, metadata, ip_address, user_agent, created_at
            FROM activity_logs
            WHERE entity_type = $1 AND entity_id = $2
            ORDER BY created_at DESC
            "#
        )
        .bind(entity_type)
        .bind(entity_id)
        .fetch_all(pool)
        .await
    }
}
