//! Database-agnostic authentication repository implementation
//!
//! This module provides a unified interface for user authentication operations
//! that works with both PostgreSQL and SQLite databases.

use crate::database::DatabaseType;
use crate::database::connection::{DatabaseConnection, DatabaseParam};
use anyhow::Result;
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

/// Database-specific user representation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DatabaseUser {
    pub id: Uuid,
    pub email: String,
    pub username: Option<String>,
    pub display_name: Option<String>,
    pub password_hash: String,
    pub avatar_url: Option<String>,
    pub roles: Vec<String>,
    pub is_active: bool,
    pub is_verified: bool,
    pub email_verified: bool,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub last_login: Option<DateTime<Utc>>,
    pub two_factor_enabled: bool,
    pub two_factor_secret: Option<String>,
    pub backup_codes: Vec<String>,
}

/// Request struct for creating a new user
#[derive(Debug, Clone)]
pub struct CreateUserRequest {
    pub email: String,
    pub password_hash: String,
    pub display_name: Option<String>,
    pub username: Option<String>,
    pub is_verified: bool,
    pub is_active: bool,
}

/// Request struct for OAuth user creation
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct OAuthUserRequest {
    pub email: String,
    pub display_name: Option<String>,
    pub username: Option<String>,
    pub provider: String,
    pub provider_id: String,
    pub provider_data: serde_json::Value,
}

/// Request struct for creating a session
#[derive(Debug, Clone)]
pub struct CreateSessionRequest {
    pub user_id: Uuid,
    pub token: String,
    pub expires_at: DateTime<Utc>,
    pub user_agent: Option<String>,
    pub ip_address: Option<String>,
}

/// User session representation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UserSession {
    pub id: Uuid,
    pub user_id: Uuid,
    pub token: String,
    pub expires_at: DateTime<Utc>,
    pub created_at: DateTime<Utc>,
    pub last_used_at: Option<DateTime<Utc>>,
    pub user_agent: Option<String>,
    pub ip_address: Option<String>,
    pub is_active: bool,
}

/// Database-agnostic authentication repository trait
#[async_trait]
#[allow(dead_code)]
pub trait AuthRepositoryTrait: Send + Sync + Clone + 'static {
    /// Initialize database tables
    async fn init_tables(&self) -> Result<()>;

    /// Create a new user
    async fn create_user(&self, user: &CreateUserRequest) -> Result<DatabaseUser>;

    /// Find user by email
    async fn find_user_by_email(&self, email: &str) -> Result<Option<DatabaseUser>>;

    /// Find user by ID
    async fn find_user_by_id(&self, id: &Uuid) -> Result<Option<DatabaseUser>>;

    /// Update user information
    async fn update_user(&self, user: &DatabaseUser) -> Result<()>;

    /// Delete user
    async fn delete_user(&self, id: &Uuid) -> Result<()>;

    /// Verify user password
    async fn verify_password(&self, email: &str, password_hash: &str) -> Result<bool>;

    /// Update user password
    async fn update_password(&self, id: &Uuid, password_hash: &str) -> Result<()>;

    /// Get user roles
    async fn get_user_roles(&self, id: &Uuid) -> Result<Vec<String>>;

    /// Add role to user
    async fn add_user_role(&self, id: &Uuid, role: &str) -> Result<()>;

    /// Remove role from user
    async fn remove_user_role(&self, id: &Uuid, role: &str) -> Result<()>;

    /// Create OAuth user
    async fn create_oauth_user(&self, user: &OAuthUserRequest) -> Result<DatabaseUser>;

    /// Find user by OAuth provider
    async fn find_user_by_oauth(
        &self,
        provider: &str,
        provider_id: &str,
    ) -> Result<Option<DatabaseUser>>;

    /// Get user profile
    async fn get_user_profile(&self, id: &Uuid) -> Result<Option<DatabaseUser>>;

    /// Update user profile
    async fn update_user_profile(&self, user: &DatabaseUser) -> Result<()>;

    /// Get user sessions
    async fn get_user_sessions(&self, user_id: &Uuid) -> Result<Vec<UserSession>>;

    /// Create session
    async fn create_session(&self, session: &CreateSessionRequest) -> Result<UserSession>;

    /// Get session by token
    async fn get_session_by_token(&self, token: &str) -> Result<Option<UserSession>>;

    /// Update session
    async fn update_session(&self, session: &UserSession) -> Result<()>;

    /// Delete session
    async fn delete_session(&self, token: &str) -> Result<()>;

    /// Cleanup expired sessions
    async fn cleanup_expired_sessions(&self) -> Result<u64>;

    /// Check if email exists
    async fn email_exists(&self, email: &str) -> Result<bool>;

    /// Check if username exists
    async fn username_exists(&self, username: &str) -> Result<bool>;

    /// Find session by ID
    async fn find_session(&self, session_id: &str) -> Result<Option<UserSession>>;

    /// Update session last accessed time
    async fn update_session_accessed(&self, session_id: &str) -> Result<()>;

    /// Update last login time
    async fn update_last_login(&self, user_id: Uuid) -> Result<()>;

    /// Invalidate all user sessions
    async fn invalidate_all_user_sessions(&self, user_id: Uuid) -> Result<()>;

    /// Create OAuth account link
    async fn create_oauth_account(
        &self,
        user_id: Uuid,
        provider: &str,
        provider_id: &str,
    ) -> Result<()>;

    /// Find user by OAuth account
    async fn find_user_by_oauth_account(
        &self,
        provider: &str,
        provider_id: &str,
    ) -> Result<Option<DatabaseUser>>;

    /// Create token for password reset, verification, etc.
    async fn create_token(
        &self,
        user_id: Uuid,
        token_type: &str,
        token_hash: &str,
        expires_at: chrono::DateTime<chrono::Utc>,
    ) -> Result<()>;

    /// Find token by hash and type
    async fn find_token(
        &self,
        token_hash: &str,
        token_type: &str,
    ) -> Result<Option<(Uuid, chrono::DateTime<chrono::Utc>)>>;

    /// Mark token as used
    async fn use_token(&self, token_hash: &str, token_type: &str) -> Result<()>;

    /// Verify user email address
    async fn verify_email(&self, user_id: Uuid) -> Result<()>;

    /// Cleanup expired tokens
    async fn cleanup_expired_tokens(&self) -> Result<u64>;
}

/// Database-agnostic authentication repository implementation
#[derive(Debug, Clone)]
pub struct AuthRepository {
    database: DatabaseConnection,
}

impl AuthRepository {
    /// Create a new auth repository with a database connection
    pub fn new(database: DatabaseConnection) -> Self {
        Self { database }
    }

    /// Get the database type
    pub fn database_type(&self) -> DatabaseType {
        self.database.database_type()
    }

    /// Create from database pool (convenience method)
    pub fn from_pool(pool: &crate::database::DatabasePool) -> Self {
        let connection = DatabaseConnection::from_pool(pool);
        Self::new(connection)
    }

    /// Get a reference to the database connection (for compatibility)
    pub fn pool(&self) -> &DatabaseConnection {
        &self.database
    }
}

#[async_trait]
impl AuthRepositoryTrait for AuthRepository {
    async fn init_tables(&self) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.init_postgres_tables().await,
            DatabaseType::SQLite => self.init_sqlite_tables().await,
        }
    }

    async fn create_user(&self, user: &CreateUserRequest) -> Result<DatabaseUser> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.create_user_postgres(user).await,
            DatabaseType::SQLite => self.create_user_sqlite(user).await,
        }
    }

    async fn find_user_by_email(&self, email: &str) -> Result<Option<DatabaseUser>> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.find_user_by_email_postgres(email).await,
            DatabaseType::SQLite => self.find_user_by_email_sqlite(email).await,
        }
    }

    async fn find_user_by_id(&self, id: &Uuid) -> Result<Option<DatabaseUser>> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.find_user_by_id_postgres(id).await,
            DatabaseType::SQLite => self.find_user_by_id_sqlite(id).await,
        }
    }

    async fn update_user(&self, user: &DatabaseUser) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.update_user_postgres(user).await,
            DatabaseType::SQLite => self.update_user_sqlite(user).await,
        }
    }

    async fn delete_user(&self, id: &Uuid) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.delete_user_postgres(id).await,
            DatabaseType::SQLite => self.delete_user_sqlite(id).await,
        }
    }

    async fn verify_password(&self, email: &str, password_hash: &str) -> Result<bool> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.verify_password_postgres(email, password_hash).await,
            DatabaseType::SQLite => self.verify_password_sqlite(email, password_hash).await,
        }
    }

    async fn update_password(&self, id: &Uuid, password_hash: &str) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.update_password_postgres(id, password_hash).await,
            DatabaseType::SQLite => self.update_password_sqlite(id, password_hash).await,
        }
    }

    async fn get_user_roles(&self, id: &Uuid) -> Result<Vec<String>> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.get_user_roles_postgres(id).await,
            DatabaseType::SQLite => self.get_user_roles_sqlite(id).await,
        }
    }

    async fn add_user_role(&self, id: &Uuid, role: &str) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.add_user_role_postgres(id, role).await,
            DatabaseType::SQLite => self.add_user_role_sqlite(id, role).await,
        }
    }

    async fn remove_user_role(&self, id: &Uuid, role: &str) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.remove_user_role_postgres(id, role).await,
            DatabaseType::SQLite => self.remove_user_role_sqlite(id, role).await,
        }
    }

    async fn create_oauth_user(&self, user: &OAuthUserRequest) -> Result<DatabaseUser> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.create_oauth_user_postgres(user).await,
            DatabaseType::SQLite => self.create_oauth_user_sqlite(user).await,
        }
    }

    async fn find_user_by_oauth(
        &self,
        provider: &str,
        provider_id: &str,
    ) -> Result<Option<DatabaseUser>> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => {
                self.find_user_by_oauth_postgres(provider, provider_id)
                    .await
            }
            DatabaseType::SQLite => self.find_user_by_oauth_sqlite(provider, provider_id).await,
        }
    }

    async fn get_user_profile(&self, id: &Uuid) -> Result<Option<DatabaseUser>> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.get_user_profile_postgres(id).await,
            DatabaseType::SQLite => self.get_user_profile_sqlite(id).await,
        }
    }

    async fn update_user_profile(&self, user: &DatabaseUser) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.update_user_profile_postgres(user).await,
            DatabaseType::SQLite => self.update_user_profile_sqlite(user).await,
        }
    }

    async fn get_user_sessions(&self, user_id: &Uuid) -> Result<Vec<UserSession>> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.get_user_sessions_postgres(user_id).await,
            DatabaseType::SQLite => self.get_user_sessions_sqlite(user_id).await,
        }
    }

    async fn create_session(&self, session: &CreateSessionRequest) -> Result<UserSession> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.create_session_postgres(session).await,
            DatabaseType::SQLite => self.create_session_sqlite(session).await,
        }
    }

    async fn get_session_by_token(&self, token: &str) -> Result<Option<UserSession>> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.get_session_by_token_postgres(token).await,
            DatabaseType::SQLite => self.get_session_by_token_sqlite(token).await,
        }
    }

    async fn update_session(&self, session: &UserSession) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.update_session_postgres(session).await,
            DatabaseType::SQLite => self.update_session_sqlite(session).await,
        }
    }

    async fn delete_session(&self, token: &str) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.delete_session_postgres(token).await,
            DatabaseType::SQLite => self.delete_session_sqlite(token).await,
        }
    }

    async fn cleanup_expired_sessions(&self) -> Result<u64> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.cleanup_expired_sessions_postgres().await,
            DatabaseType::SQLite => self.cleanup_expired_sessions_sqlite().await,
        }
    }

    async fn email_exists(&self, email: &str) -> Result<bool> {
        match self.find_user_by_email(email).await {
            Ok(Some(_)) => Ok(true),
            Ok(None) => Ok(false),
            Err(e) => Err(e),
        }
    }

    async fn username_exists(&self, username: &str) -> Result<bool> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.username_exists_postgres(username).await,
            DatabaseType::SQLite => self.username_exists_sqlite(username).await,
        }
    }

    async fn find_session(&self, session_id: &str) -> Result<Option<UserSession>> {
        self.get_session_by_token(session_id).await
    }

    async fn update_session_accessed(&self, session_id: &str) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.update_session_accessed_postgres(session_id).await,
            DatabaseType::SQLite => self.update_session_accessed_sqlite(session_id).await,
        }
    }

    async fn update_last_login(&self, user_id: Uuid) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.update_last_login_postgres(user_id).await,
            DatabaseType::SQLite => self.update_last_login_sqlite(user_id).await,
        }
    }

    async fn invalidate_all_user_sessions(&self, user_id: Uuid) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.invalidate_all_user_sessions_postgres(user_id).await,
            DatabaseType::SQLite => self.invalidate_all_user_sessions_sqlite(user_id).await,
        }
    }

    async fn create_oauth_account(
        &self,
        user_id: Uuid,
        provider: &str,
        provider_id: &str,
    ) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => {
                self.create_oauth_account_postgres(user_id, provider, provider_id)
                    .await
            }
            DatabaseType::SQLite => {
                self.create_oauth_account_sqlite(user_id, provider, provider_id)
                    .await
            }
        }
    }

    async fn find_user_by_oauth_account(
        &self,
        provider: &str,
        provider_id: &str,
    ) -> Result<Option<DatabaseUser>> {
        self.find_user_by_oauth(provider, provider_id).await
    }

    async fn create_token(
        &self,
        user_id: Uuid,
        token_type: &str,
        token_hash: &str,
        expires_at: chrono::DateTime<chrono::Utc>,
    ) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => {
                self.create_token_postgres(user_id, token_type, token_hash, expires_at)
                    .await
            }
            DatabaseType::SQLite => {
                self.create_token_sqlite(user_id, token_type, token_hash, expires_at)
                    .await
            }
        }
    }

    async fn find_token(
        &self,
        token_hash: &str,
        token_type: &str,
    ) -> Result<Option<(Uuid, chrono::DateTime<chrono::Utc>)>> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.find_token_postgres(token_hash, token_type).await,
            DatabaseType::SQLite => self.find_token_sqlite(token_hash, token_type).await,
        }
    }

    async fn use_token(&self, token_hash: &str, token_type: &str) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.use_token_postgres(token_hash, token_type).await,
            DatabaseType::SQLite => self.use_token_sqlite(token_hash, token_type).await,
        }
    }

    async fn verify_email(&self, user_id: Uuid) -> Result<()> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.verify_email_postgres(user_id).await,
            DatabaseType::SQLite => self.verify_email_sqlite(user_id).await,
        }
    }

    async fn cleanup_expired_tokens(&self) -> Result<u64> {
        match self.database.database_type() {
            DatabaseType::PostgreSQL => self.cleanup_expired_tokens_postgres().await,
            DatabaseType::SQLite => self.cleanup_expired_tokens_sqlite().await,
        }
    }
}

// PostgreSQL implementations
impl AuthRepository {
    async fn init_postgres_tables(&self) -> Result<()> {
        // Create users table
        let create_users_table = r#"
            CREATE TABLE IF NOT EXISTS users (
                id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
                email VARCHAR(255) UNIQUE NOT NULL,
                username VARCHAR(255) UNIQUE,
                display_name VARCHAR(255),
                password_hash VARCHAR(255) NOT NULL,
                avatar_url TEXT,
                roles TEXT[] DEFAULT ARRAY[]::TEXT[],
                is_active BOOLEAN DEFAULT TRUE,
                is_verified BOOLEAN DEFAULT FALSE,
                email_verified BOOLEAN DEFAULT FALSE,
                created_at TIMESTAMPTZ DEFAULT NOW(),
                updated_at TIMESTAMPTZ DEFAULT NOW(),
                last_login TIMESTAMPTZ,
                two_factor_enabled BOOLEAN DEFAULT FALSE,
                two_factor_secret VARCHAR(255),
                backup_codes TEXT[] DEFAULT ARRAY[]::TEXT[]
            )
        "#;

        // Create sessions table
        let create_sessions_table = r#"
            CREATE TABLE IF NOT EXISTS user_sessions (
                id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
                user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
                token VARCHAR(255) UNIQUE NOT NULL,
                expires_at TIMESTAMPTZ NOT NULL,
                created_at TIMESTAMPTZ DEFAULT NOW(),
                last_used_at TIMESTAMPTZ,
                user_agent TEXT,
                ip_address INET,
                is_active BOOLEAN DEFAULT TRUE
            )
        "#;

        // Create OAuth providers table
        let create_oauth_table = r#"
            CREATE TABLE IF NOT EXISTS oauth_providers (
                id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
                user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
                provider VARCHAR(50) NOT NULL,
                provider_id VARCHAR(255) NOT NULL,
                provider_data JSONB,
                created_at TIMESTAMPTZ DEFAULT NOW(),
                UNIQUE(provider, provider_id)
            )
        "#;

        // Create indexes
        let create_indexes = vec![
            "CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)",
            "CREATE INDEX IF NOT EXISTS idx_users_username ON users(username)",
            "CREATE INDEX IF NOT EXISTS idx_sessions_token ON user_sessions(token)",
            "CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON user_sessions(user_id)",
            "CREATE INDEX IF NOT EXISTS idx_oauth_provider ON oauth_providers(provider, provider_id)",
        ];

        self.database.execute(create_users_table, &[]).await?;
        self.database.execute(create_sessions_table, &[]).await?;
        self.database.execute(create_oauth_table, &[]).await?;

        for index in create_indexes {
            self.database.execute(index, &[]).await?;
        }

        Ok(())
    }

    async fn create_user_postgres(&self, user: &CreateUserRequest) -> Result<DatabaseUser> {
        let now = Utc::now();
        let id = Uuid::new_v4();
        let roles = serde_json::to_string(&vec!["user".to_string()])?;

        let query = r#"
            INSERT INTO users (id, email, username, display_name, password_hash, roles, is_active, is_verified, email_verified, created_at, updated_at)
            VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
            RETURNING id, email, username, display_name, password_hash, avatar_url, roles, is_active, is_verified, email_verified, created_at, updated_at, last_login, two_factor_enabled, two_factor_secret, backup_codes
        "#;

        let params = vec![
            DatabaseParam::Uuid(id),
            DatabaseParam::String(user.email.clone()),
            DatabaseParam::OptionalString(user.username.clone()),
            DatabaseParam::OptionalString(user.display_name.clone()),
            DatabaseParam::String(user.password_hash.clone()),
            DatabaseParam::String(roles),
            DatabaseParam::Bool(user.is_active),
            DatabaseParam::Bool(user.is_verified),
            DatabaseParam::Bool(user.is_verified),
            DatabaseParam::DateTime(now),
            DatabaseParam::DateTime(now),
        ];

        let row = self.database.fetch_one(query, &params).await?;

        Ok(DatabaseUser {
            id: row.get_uuid("id")?,
            email: row.get_string("email")?,
            username: row.get_optional_string("username")?,
            display_name: row.get_optional_string("display_name")?,
            password_hash: row.get_string("password_hash")?,
            avatar_url: row.get_optional_string("avatar_url")?,
            roles: serde_json::from_str(&row.get_string("roles")?).unwrap_or_default(),
            is_active: row.get_bool("is_active")?,
            is_verified: row.get_bool("is_verified")?,
            email_verified: row.get_bool("email_verified")?,
            created_at: row.get_datetime("created_at")?,
            updated_at: row.get_datetime("updated_at")?,
            last_login: row.get_optional_datetime("last_login")?,
            two_factor_enabled: row.get_bool("two_factor_enabled")?,
            two_factor_secret: row.get_optional_string("two_factor_secret")?,
            backup_codes: serde_json::from_str(
                &row.get_optional_string("backup_codes")?.unwrap_or_default(),
            )
            .unwrap_or_default(),
        })
    }

    async fn find_user_by_email_postgres(&self, email: &str) -> Result<Option<DatabaseUser>> {
        let query = r#"
            SELECT id, email, username, display_name, password_hash, avatar_url, roles, is_active, is_verified, email_verified, created_at, updated_at, last_login, two_factor_enabled, two_factor_secret, backup_codes
            FROM users WHERE email = $1
        "#;

        let params = vec![DatabaseParam::String(email.to_string())];
        let row = self.database.fetch_optional(query, &params).await?;

        Ok(row.map(|r| DatabaseUser {
            id: r.get_uuid("id").unwrap(),
            email: r.get_string("email").unwrap(),
            username: r.get_optional_string("username").unwrap(),
            display_name: r.get_optional_string("display_name").unwrap(),
            password_hash: r.get_string("password_hash").unwrap(),
            avatar_url: r.get_optional_string("avatar_url").unwrap(),
            roles: serde_json::from_str(&r.get_string("roles").unwrap()).unwrap_or_default(),
            is_active: r.get_bool("is_active").unwrap(),
            is_verified: r.get_bool("is_verified").unwrap(),
            email_verified: r.get_bool("email_verified").unwrap(),
            created_at: r.get_datetime("created_at").unwrap(),
            updated_at: r.get_datetime("updated_at").unwrap(),
            last_login: r.get_optional_datetime("last_login").unwrap(),
            two_factor_enabled: r.get_bool("two_factor_enabled").unwrap(),
            two_factor_secret: r.get_optional_string("two_factor_secret").unwrap(),
            backup_codes: serde_json::from_str(
                &r.get_optional_string("backup_codes")
                    .unwrap()
                    .unwrap_or_default(),
            )
            .unwrap_or_default(),
        }))
    }

    async fn find_user_by_id_postgres(&self, id: &Uuid) -> Result<Option<DatabaseUser>> {
        let query = r#"
            SELECT id, email, username, display_name, password_hash, avatar_url, roles, is_active, is_verified, email_verified, created_at, updated_at, last_login, two_factor_enabled, two_factor_secret, backup_codes
            FROM users WHERE id = $1
        "#;

        let params = vec![DatabaseParam::Uuid(*id)];
        let row = self.database.fetch_optional(query, &params).await?;

        Ok(row.map(|r| DatabaseUser {
            id: r.get_uuid("id").unwrap(),
            email: r.get_string("email").unwrap(),
            username: r.get_optional_string("username").unwrap(),
            display_name: r.get_optional_string("display_name").unwrap(),
            password_hash: r.get_string("password_hash").unwrap(),
            avatar_url: r.get_optional_string("avatar_url").unwrap(),
            roles: serde_json::from_str(&r.get_string("roles").unwrap()).unwrap_or_default(),
            is_active: r.get_bool("is_active").unwrap(),
            is_verified: r.get_bool("is_verified").unwrap(),
            email_verified: r.get_bool("email_verified").unwrap(),
            created_at: r.get_datetime("created_at").unwrap(),
            updated_at: r.get_datetime("updated_at").unwrap(),
            last_login: r.get_optional_datetime("last_login").unwrap(),
            two_factor_enabled: r.get_bool("two_factor_enabled").unwrap(),
            two_factor_secret: r.get_optional_string("two_factor_secret").unwrap(),
            backup_codes: serde_json::from_str(
                &r.get_optional_string("backup_codes")
                    .unwrap()
                    .unwrap_or_default(),
            )
            .unwrap_or_default(),
        }))
    }

    // SQLite implementations
    async fn init_sqlite_tables(&self) -> Result<()> {
        // Create users table
        let create_users_table = r#"
            CREATE TABLE IF NOT EXISTS users (
                id TEXT PRIMARY KEY,
                email TEXT UNIQUE NOT NULL,
                username TEXT UNIQUE,
                display_name TEXT,
                password_hash TEXT NOT NULL,
                avatar_url TEXT,
                roles TEXT DEFAULT '[]',
                is_active BOOLEAN DEFAULT TRUE,
                is_verified BOOLEAN DEFAULT FALSE,
                email_verified BOOLEAN DEFAULT FALSE,
                created_at TEXT NOT NULL,
                updated_at TEXT NOT NULL,
                last_login TEXT,
                two_factor_enabled BOOLEAN DEFAULT FALSE,
                two_factor_secret TEXT,
                backup_codes TEXT DEFAULT '[]'
            )
        "#;

        // Create sessions table
        let create_sessions_table = r#"
            CREATE TABLE IF NOT EXISTS user_sessions (
                id TEXT PRIMARY KEY,
                user_id TEXT NOT NULL,
                token TEXT UNIQUE NOT NULL,
                expires_at TEXT NOT NULL,
                created_at TEXT NOT NULL,
                last_used_at TEXT,
                user_agent TEXT,
                ip_address TEXT,
                is_active BOOLEAN DEFAULT TRUE,
                FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
            )
        "#;

        // Create OAuth providers table
        let create_oauth_table = r#"
            CREATE TABLE IF NOT EXISTS oauth_providers (
                id TEXT PRIMARY KEY,
                user_id TEXT NOT NULL,
                provider TEXT NOT NULL,
                provider_id TEXT NOT NULL,
                provider_data TEXT,
                created_at TEXT NOT NULL,
                FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
                UNIQUE(provider, provider_id)
            )
        "#;

        // Create indexes
        let create_indexes = vec![
            "CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)",
            "CREATE INDEX IF NOT EXISTS idx_users_username ON users(username)",
            "CREATE INDEX IF NOT EXISTS idx_sessions_token ON user_sessions(token)",
            "CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON user_sessions(user_id)",
            "CREATE INDEX IF NOT EXISTS idx_oauth_provider ON oauth_providers(provider, provider_id)",
        ];

        self.database.execute(create_users_table, &[]).await?;
        self.database.execute(create_sessions_table, &[]).await?;
        self.database.execute(create_oauth_table, &[]).await?;

        for index in create_indexes {
            self.database.execute(index, &[]).await?;
        }

        Ok(())
    }

    async fn create_user_sqlite(&self, user: &CreateUserRequest) -> Result<DatabaseUser> {
        let now = Utc::now();
        let id = Uuid::new_v4();
        let roles = serde_json::to_string(&vec!["user".to_string()])?;

        let query = r#"
            INSERT INTO users (id, email, username, display_name, password_hash, roles, is_active, is_verified, email_verified, created_at, updated_at)
            VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)
        "#;

        let params = vec![
            DatabaseParam::String(id.to_string()),
            DatabaseParam::String(user.email.clone()),
            DatabaseParam::OptionalString(user.username.clone()),
            DatabaseParam::OptionalString(user.display_name.clone()),
            DatabaseParam::String(user.password_hash.clone()),
            DatabaseParam::String(roles),
            DatabaseParam::Bool(user.is_active),
            DatabaseParam::Bool(user.is_verified),
            DatabaseParam::Bool(user.is_verified),
            DatabaseParam::String(now.to_rfc3339()),
            DatabaseParam::String(now.to_rfc3339()),
        ];

        self.database.execute(query, &params).await?;

        Ok(DatabaseUser {
            id,
            email: user.email.clone(),
            username: user.username.clone(),
            display_name: user.display_name.clone(),
            password_hash: user.password_hash.clone(),
            avatar_url: None,
            roles: vec!["user".to_string()],
            is_active: user.is_active,
            is_verified: user.is_verified,
            email_verified: user.is_verified,
            created_at: now,
            updated_at: now,
            last_login: None,
            two_factor_enabled: false,
            two_factor_secret: None,
            backup_codes: Vec::new(),
        })
    }

    async fn find_user_by_email_sqlite(&self, email: &str) -> Result<Option<DatabaseUser>> {
        let query = r#"
            SELECT id, email, username, display_name, password_hash, avatar_url, roles, is_active, is_verified, email_verified, created_at, updated_at, last_login, two_factor_enabled, two_factor_secret, backup_codes
            FROM users WHERE email = ?1
        "#;

        let params = vec![DatabaseParam::String(email.to_string())];
        let row = self.database.fetch_optional(query, &params).await?;

        Ok(row.map(|r| DatabaseUser {
            id: Uuid::parse_str(&r.get_string("id").unwrap()).unwrap(),
            email: r.get_string("email").unwrap(),
            username: r.get_optional_string("username").unwrap(),
            display_name: r.get_optional_string("display_name").unwrap(),
            password_hash: r.get_string("password_hash").unwrap(),
            avatar_url: r.get_optional_string("avatar_url").unwrap(),
            roles: serde_json::from_str(&r.get_string("roles").unwrap()).unwrap_or_default(),
            is_active: r.get_bool("is_active").unwrap(),
            is_verified: r.get_bool("is_verified").unwrap(),
            email_verified: r.get_bool("email_verified").unwrap(),
            created_at: DateTime::parse_from_rfc3339(&r.get_string("created_at").unwrap())
                .unwrap()
                .with_timezone(&Utc),
            updated_at: DateTime::parse_from_rfc3339(&r.get_string("updated_at").unwrap())
                .unwrap()
                .with_timezone(&Utc),
            last_login: r.get_optional_string("last_login").unwrap().map(|s| {
                DateTime::parse_from_rfc3339(&s)
                    .unwrap()
                    .with_timezone(&Utc)
            }),
            two_factor_enabled: r.get_bool("two_factor_enabled").unwrap(),
            two_factor_secret: r.get_optional_string("two_factor_secret").unwrap(),
            backup_codes: serde_json::from_str(
                &r.get_optional_string("backup_codes")
                    .unwrap()
                    .unwrap_or_default(),
            )
            .unwrap_or_default(),
        }))
    }

    async fn find_user_by_id_sqlite(&self, id: &Uuid) -> Result<Option<DatabaseUser>> {
        let query = r#"
            SELECT id, email, username, display_name, password_hash, avatar_url, roles, is_active, is_verified, email_verified, created_at, updated_at, last_login, two_factor_enabled, two_factor_secret, backup_codes
            FROM users WHERE id = ?1
        "#;

        let params = vec![DatabaseParam::String(id.to_string())];
        let row = self.database.fetch_optional(query, &params).await?;

        Ok(row.map(|r| DatabaseUser {
            id: Uuid::parse_str(&r.get_string("id").unwrap()).unwrap(),
            email: r.get_string("email").unwrap(),
            username: r.get_optional_string("username").unwrap(),
            display_name: r.get_optional_string("display_name").unwrap(),
            password_hash: r.get_string("password_hash").unwrap(),
            avatar_url: r.get_optional_string("avatar_url").unwrap(),
            roles: serde_json::from_str(&r.get_string("roles").unwrap()).unwrap_or_default(),
            is_active: r.get_bool("is_active").unwrap(),
            is_verified: r.get_bool("is_verified").unwrap(),
            email_verified: r.get_bool("email_verified").unwrap(),
            created_at: DateTime::parse_from_rfc3339(&r.get_string("created_at").unwrap())
                .unwrap()
                .with_timezone(&Utc),
            updated_at: DateTime::parse_from_rfc3339(&r.get_string("updated_at").unwrap())
                .unwrap()
                .with_timezone(&Utc),
            last_login: r.get_optional_string("last_login").unwrap().map(|s| {
                DateTime::parse_from_rfc3339(&s)
                    .unwrap()
                    .with_timezone(&Utc)
            }),
            two_factor_enabled: r.get_bool("two_factor_enabled").unwrap(),
            two_factor_secret: r.get_optional_string("two_factor_secret").unwrap(),
            backup_codes: serde_json::from_str(
                &r.get_optional_string("backup_codes")
                    .unwrap()
                    .unwrap_or_default(),
            )
            .unwrap_or_default(),
        }))
    }

    // Stub implementations for remaining methods
    async fn update_user_postgres(&self, _user: &DatabaseUser) -> Result<()> {
        // TODO: Implement user update for PostgreSQL
        Ok(())
    }

    async fn update_user_sqlite(&self, _user: &DatabaseUser) -> Result<()> {
        // TODO: Implement user update for SQLite
        Ok(())
    }

    async fn delete_user_postgres(&self, _id: &Uuid) -> Result<()> {
        // TODO: Implement user deletion for PostgreSQL
        Ok(())
    }

    async fn delete_user_sqlite(&self, _id: &Uuid) -> Result<()> {
        // TODO: Implement user deletion for SQLite
        Ok(())
    }

    async fn verify_password_postgres(&self, email: &str, password_hash: &str) -> Result<bool> {
        let query = "SELECT password_hash FROM users WHERE email = $1 AND is_active = true LIMIT 1";
        let params = vec![DatabaseParam::String(email.to_string())];

        match self.database.fetch_optional(query, &params).await? {
            Some(row) => {
                let stored_hash = row.get_string("password_hash")?;
                Ok(stored_hash == password_hash)
            }
            None => Ok(false),
        }
    }

    async fn verify_password_sqlite(&self, email: &str, password_hash: &str) -> Result<bool> {
        let query = "SELECT password_hash FROM users WHERE email = ? AND is_active = 1 LIMIT 1";
        let params = vec![DatabaseParam::String(email.to_string())];

        match self.database.fetch_optional(query, &params).await? {
            Some(row) => {
                let stored_hash = row.get_string("password_hash")?;
                Ok(stored_hash == password_hash)
            }
            None => Ok(false),
        }
    }

    async fn update_password_postgres(&self, id: &Uuid, password_hash: &str) -> Result<()> {
        let query = "UPDATE users SET password_hash = $1, updated_at = NOW() WHERE id = $2";
        let params = vec![
            DatabaseParam::String(password_hash.to_string()),
            DatabaseParam::Uuid(*id),
        ];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn update_password_sqlite(&self, id: &Uuid, password_hash: &str) -> Result<()> {
        let query = "UPDATE users SET password_hash = ?, updated_at = datetime('now') WHERE id = ?";
        let params = vec![
            DatabaseParam::String(password_hash.to_string()),
            DatabaseParam::String(id.to_string()),
        ];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn get_user_roles_postgres(&self, _id: &Uuid) -> Result<Vec<String>> {
        // TODO: Implement get user roles for PostgreSQL
        Ok(vec![])
    }

    async fn get_user_roles_sqlite(&self, _id: &Uuid) -> Result<Vec<String>> {
        // TODO: Implement get user roles for SQLite
        Ok(vec![])
    }

    async fn add_user_role_postgres(&self, _id: &Uuid, _role: &str) -> Result<()> {
        // TODO: Implement add user role for PostgreSQL
        Ok(())
    }

    async fn add_user_role_sqlite(&self, _id: &Uuid, _role: &str) -> Result<()> {
        // TODO: Implement add user role for SQLite
        Ok(())
    }

    async fn remove_user_role_postgres(&self, _id: &Uuid, _role: &str) -> Result<()> {
        // TODO: Implement remove user role for PostgreSQL
        Ok(())
    }

    async fn remove_user_role_sqlite(&self, _id: &Uuid, _role: &str) -> Result<()> {
        // TODO: Implement remove user role for SQLite
        Ok(())
    }

    async fn create_oauth_user_postgres(&self, _user: &OAuthUserRequest) -> Result<DatabaseUser> {
        // TODO: Implement OAuth user creation for PostgreSQL
        Err(anyhow::anyhow!("Not implemented"))
    }

    async fn create_oauth_user_sqlite(&self, _user: &OAuthUserRequest) -> Result<DatabaseUser> {
        // TODO: Implement OAuth user creation for SQLite
        Err(anyhow::anyhow!("Not implemented"))
    }

    async fn find_user_by_oauth_postgres(
        &self,
        provider: &str,
        provider_id: &str,
    ) -> Result<Option<DatabaseUser>> {
        let query = r#"
            SELECT u.id, u.email, u.username, u.display_name, u.password_hash, u.avatar_url,
                   u.roles, u.is_active, u.is_verified, u.email_verified, u.created_at,
                   u.updated_at, u.last_login, u.two_factor_enabled, u.two_factor_secret, u.backup_codes
            FROM users u
            JOIN oauth_providers o ON u.id = o.user_id
            WHERE o.provider = $1 AND o.provider_id = $2 AND u.is_active = true
            LIMIT 1
        "#;
        let params = vec![
            DatabaseParam::String(provider.to_string()),
            DatabaseParam::String(provider_id.to_string()),
        ];

        match self.database.fetch_optional(query, &params).await? {
            Some(row) => Ok(Some(self.row_to_database_user(row)?)),
            None => Ok(None),
        }
    }

    async fn find_user_by_oauth_sqlite(
        &self,
        provider: &str,
        provider_id: &str,
    ) -> Result<Option<DatabaseUser>> {
        let query = r#"
            SELECT u.id, u.email, u.username, u.display_name, u.password_hash, u.avatar_url,
                   u.roles, u.is_active, u.is_verified, u.email_verified, u.created_at,
                   u.updated_at, u.last_login, u.two_factor_enabled, u.two_factor_secret, u.backup_codes
            FROM users u
            JOIN oauth_providers o ON u.id = o.user_id
            WHERE o.provider = ? AND o.provider_id = ? AND u.is_active = 1
            LIMIT 1
        "#;
        let params = vec![
            DatabaseParam::String(provider.to_string()),
            DatabaseParam::String(provider_id.to_string()),
        ];

        match self.database.fetch_optional(query, &params).await? {
            Some(row) => Ok(Some(self.row_to_database_user(row)?)),
            None => Ok(None),
        }
    }

    async fn get_user_profile_postgres(&self, _id: &Uuid) -> Result<Option<DatabaseUser>> {
        // TODO: Implement get user profile for PostgreSQL
        Ok(None)
    }

    async fn get_user_profile_sqlite(&self, _id: &Uuid) -> Result<Option<DatabaseUser>> {
        // TODO: Implement get user profile for SQLite
        Ok(None)
    }

    async fn update_user_profile_postgres(&self, _user: &DatabaseUser) -> Result<()> {
        // TODO: Implement update user profile for PostgreSQL
        Ok(())
    }

    async fn update_user_profile_sqlite(&self, _user: &DatabaseUser) -> Result<()> {
        // TODO: Implement update user profile for SQLite
        Ok(())
    }

    async fn get_user_sessions_postgres(&self, _user_id: &Uuid) -> Result<Vec<UserSession>> {
        // TODO: Implement get user sessions for PostgreSQL
        Ok(vec![])
    }

    async fn get_user_sessions_sqlite(&self, _user_id: &Uuid) -> Result<Vec<UserSession>> {
        // TODO: Implement get user sessions for SQLite
        Ok(vec![])
    }

    async fn create_session_postgres(&self, session: &CreateSessionRequest) -> Result<UserSession> {
        let id = Uuid::new_v4();
        let now = Utc::now();

        let query = r#"
            INSERT INTO user_sessions (id, user_id, token, expires_at, created_at, last_used_at, user_agent, ip_address, is_active)
            VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
            RETURNING id, user_id, token, expires_at, created_at, last_used_at, user_agent, ip_address, is_active
        "#;

        let params = vec![
            DatabaseParam::Uuid(id),
            DatabaseParam::Uuid(session.user_id),
            DatabaseParam::String(session.token.clone()),
            DatabaseParam::DateTime(session.expires_at),
            DatabaseParam::DateTime(now),
            DatabaseParam::DateTime(now),
            DatabaseParam::OptionalString(session.user_agent.clone()),
            DatabaseParam::OptionalString(session.ip_address.clone()),
            DatabaseParam::Bool(true),
        ];

        let row = self.database.fetch_one(query, &params).await?;

        Ok(UserSession {
            id: row.get_uuid("id")?,
            user_id: row.get_uuid("user_id")?,
            token: row.get_string("token")?,
            expires_at: row.get_datetime("expires_at")?,
            created_at: row.get_datetime("created_at")?,
            last_used_at: row.get_optional_datetime("last_used_at")?,
            user_agent: row.get_optional_string("user_agent")?,
            ip_address: row.get_optional_string("ip_address")?,
            is_active: row.get_bool("is_active")?,
        })
    }

    async fn create_session_sqlite(&self, session: &CreateSessionRequest) -> Result<UserSession> {
        let id = Uuid::new_v4();
        let now = Utc::now();

        let query = r#"
            INSERT INTO user_sessions (id, user_id, token, expires_at, created_at, last_used_at, user_agent, ip_address, is_active)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
            RETURNING id, user_id, token, expires_at, created_at, last_used_at, user_agent, ip_address, is_active
        "#;

        let params = vec![
            DatabaseParam::String(id.to_string()),
            DatabaseParam::String(session.user_id.to_string()),
            DatabaseParam::String(session.token.clone()),
            DatabaseParam::String(session.expires_at.to_rfc3339()),
            DatabaseParam::String(now.to_rfc3339()),
            DatabaseParam::String(now.to_rfc3339()),
            DatabaseParam::OptionalString(session.user_agent.clone()),
            DatabaseParam::OptionalString(session.ip_address.clone()),
            DatabaseParam::Bool(true),
        ];

        let row = self.database.fetch_one(query, &params).await?;

        Ok(UserSession {
            id: row.get_uuid("id")?,
            user_id: row.get_uuid("user_id")?,
            token: row.get_string("token")?,
            expires_at: row.get_datetime("expires_at")?,
            created_at: row.get_datetime("created_at")?,
            last_used_at: row.get_optional_datetime("last_used_at")?,
            user_agent: row.get_optional_string("user_agent")?,
            ip_address: row.get_optional_string("ip_address")?,
            is_active: row.get_bool("is_active")?,
        })
    }

    async fn get_session_by_token_postgres(&self, token: &str) -> Result<Option<UserSession>> {
        let query = r#"
            SELECT id, user_id, token, expires_at, created_at, last_used_at, user_agent, ip_address, is_active
            FROM user_sessions
            WHERE token = $1 AND is_active = true AND expires_at > NOW()
            LIMIT 1
        "#;
        let params = vec![DatabaseParam::String(token.to_string())];

        match self.database.fetch_optional(query, &params).await? {
            Some(row) => Ok(Some(UserSession {
                id: row.get_uuid("id")?,
                user_id: row.get_uuid("user_id")?,
                token: row.get_string("token")?,
                expires_at: row.get_datetime("expires_at")?,
                created_at: row.get_datetime("created_at")?,
                last_used_at: row.get_optional_datetime("last_used_at")?,
                user_agent: row.get_optional_string("user_agent")?,
                ip_address: row.get_optional_string("ip_address")?,
                is_active: row.get_bool("is_active")?,
            })),
            None => Ok(None),
        }
    }

    async fn get_session_by_token_sqlite(&self, token: &str) -> Result<Option<UserSession>> {
        let query = r#"
            SELECT id, user_id, token, expires_at, created_at, last_used_at, user_agent, ip_address, is_active
            FROM user_sessions
            WHERE token = ? AND is_active = 1 AND expires_at > datetime('now')
            LIMIT 1
        "#;
        let params = vec![DatabaseParam::String(token.to_string())];

        match self.database.fetch_optional(query, &params).await? {
            Some(row) => Ok(Some(UserSession {
                id: row.get_uuid("id")?,
                user_id: row.get_uuid("user_id")?,
                token: row.get_string("token")?,
                expires_at: row.get_datetime("expires_at")?,
                created_at: row.get_datetime("created_at")?,
                last_used_at: row.get_optional_datetime("last_used_at")?,
                user_agent: row.get_optional_string("user_agent")?,
                ip_address: row.get_optional_string("ip_address")?,
                is_active: row.get_bool("is_active")?,
            })),
            None => Ok(None),
        }
    }

    async fn update_session_postgres(&self, _session: &UserSession) -> Result<()> {
        // TODO: Implement update session for PostgreSQL
        Ok(())
    }

    async fn update_session_sqlite(&self, _session: &UserSession) -> Result<()> {
        // TODO: Implement update session for SQLite
        Ok(())
    }

    async fn delete_session_postgres(&self, token: &str) -> Result<()> {
        let query = "DELETE FROM user_sessions WHERE token = $1";
        let params = vec![DatabaseParam::String(token.to_string())];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn delete_session_sqlite(&self, token: &str) -> Result<()> {
        let query = "DELETE FROM user_sessions WHERE token = ?";
        let params = vec![DatabaseParam::String(token.to_string())];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn cleanup_expired_sessions_postgres(&self) -> Result<u64> {
        let query = "DELETE FROM user_sessions WHERE expires_at <= NOW() OR is_active = false";

        self.database.execute(query, &[]).await?;
        // Note: In a real implementation, you'd want to return the actual count
        // This would require a different approach or counting before deletion
        Ok(0)
    }

    async fn cleanup_expired_sessions_sqlite(&self) -> Result<u64> {
        let query =
            "DELETE FROM user_sessions WHERE expires_at <= datetime('now') OR is_active = 0";

        self.database.execute(query, &[]).await?;
        // Note: In a real implementation, you'd want to return the actual count
        // This would require a different approach or counting before deletion
        Ok(0)
    }

    async fn username_exists_postgres(&self, username: &str) -> Result<bool> {
        let query = "SELECT 1 FROM users WHERE username = $1 LIMIT 1";
        let params = vec![DatabaseParam::String(username.to_string())];

        match self.database.fetch_optional(query, &params).await? {
            Some(_) => Ok(true),
            None => Ok(false),
        }
    }

    async fn username_exists_sqlite(&self, username: &str) -> Result<bool> {
        let query = "SELECT 1 FROM users WHERE username = ? LIMIT 1";
        let params = vec![DatabaseParam::String(username.to_string())];

        match self.database.fetch_optional(query, &params).await? {
            Some(_) => Ok(true),
            None => Ok(false),
        }
    }

    async fn update_session_accessed_postgres(&self, session_id: &str) -> Result<()> {
        let query =
            "UPDATE user_sessions SET last_used_at = NOW() WHERE token = $1 AND is_active = true";
        let params = vec![DatabaseParam::String(session_id.to_string())];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn update_session_accessed_sqlite(&self, session_id: &str) -> Result<()> {
        let query = "UPDATE user_sessions SET last_used_at = datetime('now') WHERE token = ? AND is_active = 1";
        let params = vec![DatabaseParam::String(session_id.to_string())];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn update_last_login_postgres(&self, user_id: Uuid) -> Result<()> {
        let query = "UPDATE users SET last_login = NOW(), updated_at = NOW() WHERE id = $1";
        let params = vec![DatabaseParam::Uuid(user_id)];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn update_last_login_sqlite(&self, user_id: Uuid) -> Result<()> {
        let query = "UPDATE users SET last_login = datetime('now'), updated_at = datetime('now') WHERE id = ?";
        let params = vec![DatabaseParam::String(user_id.to_string())];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn invalidate_all_user_sessions_postgres(&self, user_id: Uuid) -> Result<()> {
        let query = "UPDATE user_sessions SET is_active = false WHERE user_id = $1";
        let params = vec![DatabaseParam::Uuid(user_id)];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn invalidate_all_user_sessions_sqlite(&self, user_id: Uuid) -> Result<()> {
        let query = "UPDATE user_sessions SET is_active = 0 WHERE user_id = ?";
        let params = vec![DatabaseParam::String(user_id.to_string())];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn create_oauth_account_postgres(
        &self,
        user_id: Uuid,
        provider: &str,
        provider_id: &str,
    ) -> Result<()> {
        let query = r#"
            INSERT INTO oauth_providers (user_id, provider, provider_id, created_at)
            VALUES ($1, $2, $3, NOW())
            ON CONFLICT (provider, provider_id) DO NOTHING
        "#;
        let params = vec![
            DatabaseParam::Uuid(user_id),
            DatabaseParam::String(provider.to_string()),
            DatabaseParam::String(provider_id.to_string()),
        ];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn create_oauth_account_sqlite(
        &self,
        user_id: Uuid,
        provider: &str,
        provider_id: &str,
    ) -> Result<()> {
        let query = r#"
            INSERT OR IGNORE INTO oauth_providers (user_id, provider, provider_id, created_at)
            VALUES (?, ?, ?, datetime('now'))
        "#;
        let params = vec![
            DatabaseParam::String(user_id.to_string()),
            DatabaseParam::String(provider.to_string()),
            DatabaseParam::String(provider_id.to_string()),
        ];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn create_token_postgres(
        &self,
        user_id: Uuid,
        token_type: &str,
        token_hash: &str,
        expires_at: chrono::DateTime<chrono::Utc>,
    ) -> Result<()> {
        // First, ensure tokens table exists
        let create_table = r#"
            CREATE TABLE IF NOT EXISTS user_tokens (
                id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
                user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
                token_hash VARCHAR(255) NOT NULL,
                token_type VARCHAR(50) NOT NULL,
                expires_at TIMESTAMPTZ NOT NULL,
                used_at TIMESTAMPTZ,
                created_at TIMESTAMPTZ DEFAULT NOW(),
                UNIQUE(token_hash, token_type)
            )
        "#;
        self.database.execute(create_table, &[]).await?;

        let query = r#"
            INSERT INTO user_tokens (user_id, token_hash, token_type, expires_at)
            VALUES ($1, $2, $3, $4)
            ON CONFLICT (token_hash, token_type) DO UPDATE SET
            expires_at = EXCLUDED.expires_at,
            used_at = NULL
        "#;
        let params = vec![
            DatabaseParam::Uuid(user_id),
            DatabaseParam::String(token_hash.to_string()),
            DatabaseParam::String(token_type.to_string()),
            DatabaseParam::DateTime(expires_at),
        ];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn create_token_sqlite(
        &self,
        user_id: Uuid,
        token_type: &str,
        token_hash: &str,
        expires_at: chrono::DateTime<chrono::Utc>,
    ) -> Result<()> {
        // First, ensure tokens table exists
        let create_table = r#"
            CREATE TABLE IF NOT EXISTS user_tokens (
                id TEXT PRIMARY KEY DEFAULT (lower(hex(randomblob(16)))),
                user_id TEXT NOT NULL,
                token_hash TEXT NOT NULL,
                token_type TEXT NOT NULL,
                expires_at TEXT NOT NULL,
                used_at TEXT,
                created_at TEXT DEFAULT (datetime('now')),
                UNIQUE(token_hash, token_type),
                FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
            )
        "#;
        self.database.execute(create_table, &[]).await?;

        let query = r#"
            INSERT OR REPLACE INTO user_tokens (user_id, token_hash, token_type, expires_at)
            VALUES (?, ?, ?, ?)
        "#;
        let params = vec![
            DatabaseParam::String(user_id.to_string()),
            DatabaseParam::String(token_hash.to_string()),
            DatabaseParam::String(token_type.to_string()),
            DatabaseParam::String(expires_at.to_rfc3339()),
        ];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn find_token_postgres(
        &self,
        token_hash: &str,
        token_type: &str,
    ) -> Result<Option<(Uuid, chrono::DateTime<chrono::Utc>)>> {
        let query = r#"
            SELECT user_id, expires_at
            FROM user_tokens
            WHERE token_hash = $1 AND token_type = $2
            AND expires_at > NOW() AND used_at IS NULL
            LIMIT 1
        "#;
        let params = vec![
            DatabaseParam::String(token_hash.to_string()),
            DatabaseParam::String(token_type.to_string()),
        ];

        match self.database.fetch_optional(query, &params).await? {
            Some(row) => {
                let user_id = row.get_uuid("user_id")?;
                let expires_at = row.get_datetime("expires_at")?;
                Ok(Some((user_id, expires_at)))
            }
            None => Ok(None),
        }
    }

    async fn find_token_sqlite(
        &self,
        token_hash: &str,
        token_type: &str,
    ) -> Result<Option<(Uuid, chrono::DateTime<chrono::Utc>)>> {
        let query = r#"
            SELECT user_id, expires_at
            FROM user_tokens
            WHERE token_hash = ? AND token_type = ?
            AND expires_at > datetime('now') AND used_at IS NULL
            LIMIT 1
        "#;
        let params = vec![
            DatabaseParam::String(token_hash.to_string()),
            DatabaseParam::String(token_type.to_string()),
        ];

        match self.database.fetch_optional(query, &params).await? {
            Some(row) => {
                let user_id = row.get_uuid("user_id")?;
                let expires_at = row.get_datetime("expires_at")?;
                Ok(Some((user_id, expires_at)))
            }
            None => Ok(None),
        }
    }

    async fn use_token_postgres(&self, token_hash: &str, token_type: &str) -> Result<()> {
        let query = r#"
            UPDATE user_tokens
            SET used_at = NOW()
            WHERE token_hash = $1 AND token_type = $2 AND used_at IS NULL
        "#;
        let params = vec![
            DatabaseParam::String(token_hash.to_string()),
            DatabaseParam::String(token_type.to_string()),
        ];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn use_token_sqlite(&self, token_hash: &str, token_type: &str) -> Result<()> {
        let query = r#"
            UPDATE user_tokens
            SET used_at = datetime('now')
            WHERE token_hash = ? AND token_type = ? AND used_at IS NULL
        "#;
        let params = vec![
            DatabaseParam::String(token_hash.to_string()),
            DatabaseParam::String(token_type.to_string()),
        ];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn verify_email_postgres(&self, user_id: Uuid) -> Result<()> {
        let query = r#"
            UPDATE users
            SET email_verified = true, is_verified = true, updated_at = NOW()
            WHERE id = $1
        "#;
        let params = vec![DatabaseParam::Uuid(user_id)];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn verify_email_sqlite(&self, user_id: Uuid) -> Result<()> {
        let query = r#"
            UPDATE users
            SET email_verified = 1, is_verified = 1, updated_at = datetime('now')
            WHERE id = ?
        "#;
        let params = vec![DatabaseParam::String(user_id.to_string())];

        self.database.execute(query, &params).await?;
        Ok(())
    }

    async fn cleanup_expired_tokens_postgres(&self) -> Result<u64> {
        let query = "DELETE FROM user_tokens WHERE expires_at <= NOW()";

        self.database.execute(query, &[]).await?;
        // Note: In a real implementation, you'd want to return the actual count
        // This would require a different approach or counting before deletion
        Ok(0)
    }

    async fn cleanup_expired_tokens_sqlite(&self) -> Result<u64> {
        let query = "DELETE FROM user_tokens WHERE expires_at <= datetime('now')";

        self.database.execute(query, &[]).await?;
        // Note: In a real implementation, you'd want to return the actual count
        // This would require a different approach or counting before deletion
        Ok(0)
    }
    // Helper method to convert database row to DatabaseUser
    fn row_to_database_user(
        &self,
        row: crate::database::connection::DatabaseRow,
    ) -> Result<DatabaseUser> {
        let roles_json = row.get_string("roles")?;
        let roles: Vec<String> = serde_json::from_str(&roles_json)
            .map_err(|e| anyhow::anyhow!("Failed to parse roles JSON: {}", e))?;

        let backup_codes_json = row.get_optional_string("backup_codes")?;
        let backup_codes: Vec<String> = backup_codes_json
            .map(|json| serde_json::from_str(&json).unwrap_or_default())
            .unwrap_or_default();

        Ok(DatabaseUser {
            id: row.get_uuid("id")?,
            email: row.get_string("email")?,
            username: row.get_optional_string("username")?,
            display_name: row.get_optional_string("display_name")?,
            password_hash: row.get_string("password_hash")?,
            avatar_url: row.get_optional_string("avatar_url")?,
            roles,
            is_active: row.get_bool("is_active")?,
            is_verified: row.get_bool("is_verified")?,
            email_verified: row.get_bool("email_verified")?,
            created_at: row.get_datetime("created_at")?,
            updated_at: row.get_datetime("updated_at")?,
            last_login: row.get_optional_datetime("last_login")?,
            two_factor_enabled: row.get_bool("two_factor_enabled")?,
            two_factor_secret: row.get_optional_string("two_factor_secret")?,
            backup_codes,
        })
    }
}

impl From<DatabaseUser> for shared::auth::User {
    fn from(db_user: DatabaseUser) -> Self {
        Self {
            id: db_user.id,
            email: db_user.email,
            username: db_user.username.unwrap_or_default(),
            display_name: db_user.display_name,
            avatar_url: db_user.avatar_url,
            roles: db_user
                .roles
                .into_iter()
                .map(|r| match r.as_str() {
                    "admin" => shared::auth::Role::Admin,
                    "moderator" => shared::auth::Role::Moderator,
                    "user" => shared::auth::Role::User,
                    "guest" => shared::auth::Role::Guest,
                    _ => shared::auth::Role::Custom(r),
                })
                .collect(),
            is_active: db_user.is_active,
            email_verified: db_user.email_verified,
            created_at: db_user.created_at,
            updated_at: db_user.updated_at,
            last_login: db_user.last_login,
            profile: shared::auth::UserProfile::default(),
            two_factor_enabled: db_user.two_factor_enabled,
        }
    }
}

impl From<shared::auth::User> for DatabaseUser {
    fn from(user: shared::auth::User) -> Self {
        Self {
            id: user.id,
            email: user.email,
            username: Some(user.username),
            display_name: user.display_name,
            password_hash: String::new(), // This should be handled separately
            avatar_url: user.avatar_url,
            roles: user
                .roles
                .into_iter()
                .map(|r| match r {
                    shared::auth::Role::Admin => "admin".to_string(),
                    shared::auth::Role::Moderator => "moderator".to_string(),
                    shared::auth::Role::User => "user".to_string(),
                    shared::auth::Role::Guest => "guest".to_string(),
                    shared::auth::Role::Custom(name) => name,
                })
                .collect(),
            is_active: user.is_active,
            is_verified: user.email_verified,
            email_verified: user.email_verified,
            created_at: user.created_at,
            updated_at: user.updated_at,
            last_login: user.last_login,
            two_factor_enabled: user.two_factor_enabled,
            two_factor_secret: None,
            backup_codes: Vec::new(),
        }
    }
}
