Skip to content
use crate::auth::User;
use crate::db::Database;

impl Database {
    pub async fn create_user(&self, user: &User) -> Result<(), String> {
        self.conn().await?
            .execute(
                "INSERT INTO users (id, username, email, password_hash, created_at, is_admin) VALUES (?1, ?2, ?3, ?4, ?5, ?6)",
                turso::params![user.id.clone(), user.username.clone(), user.email.clone(), user.password_hash.clone(), user.created_at.clone(), user.is_admin],
            )
            .await
            .map_err(|e| e.to_string())?;
        Ok(())
    }

    pub async fn get_user_by_id(&self, user_id: &str) -> Result<Option<User>, String> {
        let mut rows = self
            .conn().await?
            .query(
                "SELECT id, username, email, password_hash, created_at, is_admin FROM users WHERE id = ?1",
                turso::params![user_id],
            )
            .await
            .map_err(|e| e.to_string())?;

        if let Some(row) = rows.next().await.map_err(|e| e.to_string())? {
            Ok(Some(User {
                id: row.get(0).map_err(|e| e.to_string())?,
                username: row.get(1).map_err(|e| e.to_string())?,
                email: row.get(2).map_err(|e| e.to_string())?,
                password_hash: row.get(3).map_err(|e| e.to_string())?,
                created_at: row.get(4).map_err(|e| e.to_string())?,
                is_admin: row.get::<bool>(5).map_err(|e| e.to_string())?,
            }))
        } else {
            Ok(None)
        }
    }

    pub async fn get_user_by_username(&self, username: &str) -> Result<Option<User>, String> {
        let mut rows = self
            .conn().await?
            .query(
                "SELECT id, username, email, password_hash, created_at, is_admin FROM users WHERE username = ?1",
                turso::params![username],
            )
            .await
            .map_err(|e| e.to_string())?;

        if let Some(row) = rows.next().await.map_err(|e| e.to_string())? {
            Ok(Some(User {
                id: row.get(0).map_err(|e| e.to_string())?,
                username: row.get(1).map_err(|e| e.to_string())?,
                email: row.get(2).map_err(|e| e.to_string())?,
                password_hash: row.get(3).map_err(|e| e.to_string())?,
                created_at: row.get(4).map_err(|e| e.to_string())?,
                is_admin: row.get::<bool>(5).map_err(|e| e.to_string())?,
            }))
        } else {
            Ok(None)
        }
    }

    pub async fn get_all_users(&self) -> Result<Vec<User>, String> {
        let mut rows = self
            .conn()
            .await?
            .query(
                "SELECT id, username, email, password_hash, created_at, is_admin FROM users ORDER BY created_at",
                (),
            )
            .await
            .map_err(|e| e.to_string())?;

        let mut result = Vec::new();
        while let Some(row) = rows.next().await.map_err(|e| e.to_string())? {
            result.push(User {
                id: row.get(0).map_err(|e| e.to_string())?,
                username: row.get(1).map_err(|e| e.to_string())?,
                email: row.get(2).map_err(|e| e.to_string())?,
                password_hash: row.get(3).map_err(|e| e.to_string())?,
                created_at: row.get(4).map_err(|e| e.to_string())?,
                is_admin: row.get::<bool>(5).map_err(|e| e.to_string())?,
            });
        }
        Ok(result)
    }

    pub async fn set_user_admin(&self, user_id: &str, is_admin: bool) -> Result<(), String> {
        self.conn()
            .await?
            .execute(
                "UPDATE users SET is_admin = ?1 WHERE id = ?2",
                turso::params![is_admin, user_id],
            )
            .await
            .map_err(|e| e.to_string())?;
        Ok(())
    }
}