use crate::repo::SpaceRepo;
use crate::model::space::Space;
use sqlx::PgPool;

#[derive(Clone)]
pub struct SpaceRepository {
    pool: PgPool,
}

impl SpaceRepository {
    pub fn new(pool: PgPool) -> Self {
        Self { pool }
    }
}

#[rocket::async_trait]
impl SpaceRepo for SpaceRepository {
    async fn create(&self, name: &str, description: Option<&str>, owner_id: i64) -> Result<i64, sqlx::Error> {
        let row = sqlx::query!(
            "INSERT INTO spaces (name, description, owner_id) VALUES ($1, $2, $3) RETURNING id",
            name,
            description,
            owner_id
        )
        .fetch_one(&self.pool)
        .await?;
        Ok(row.id)
    }

    async fn get_all(&self) -> Result<Vec<Space>, sqlx::Error> {
        sqlx::query_as!(Space,
            "SELECT id, name, description, owner_id, created_at, updated_at FROM spaces"
        )
        .fetch_all(&self.pool)
        .await
    }

    async fn get_by_member(&self, uid: i64) -> Result<Vec<Space>, sqlx::Error> {
        sqlx::query_as!(Space,
            "SELECT s.id, s.name, s.description, s.created_at, s.updated_at, s.owner_id
                FROM spaces s JOIN space_members sm ON s.id = sm.space_id
                WHERE sm.user_id = $1",
            uid
        ).fetch_all(&self.pool)
        .await
    }

    async fn get_by_id(&self, id: i64) -> Result<Option<Space>, sqlx::Error> {
        sqlx::query_as!(Space,
            "SELECT id, name, description, owner_id, created_at, updated_at FROM spaces WHERE id = $1",
            id
        )
        .fetch_optional(&self.pool)
        .await
    }
}
