"""
Database module for Toxo - handles user authentication and data persistence.
"""

import sqlite3
import hashlib
import bcrypt
from typing import Optional, List, Dict, Any
from datetime import datetime, timedelta
from pathlib import Path
import json
import uuid

from ..utils.logger import get_logger
from ..utils.exceptions import SecurityError


class DatabaseManager:
    """
    Manages SQLite database for user authentication and application data.
    """
    
    def __init__(self, db_path: str = None):
        self.logger = get_logger(__name__)
        
        # Use default path if not provided
        if db_path is None:
            # Create database in user's home directory
            home_dir = Path.home() / ".toxo"
            home_dir.mkdir(exist_ok=True)
            db_path = str(home_dir / "toxo_users.db")
        
        self.db_path = db_path
        self.init_database()
        
    def init_database(self):
        """Initialize database with proper schema."""
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # Create users table
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS users (
                    id TEXT PRIMARY KEY,
                    email TEXT UNIQUE NOT NULL,
                    name TEXT NOT NULL,
                    password_hash TEXT NOT NULL,
                    salt TEXT NOT NULL,
                    subscription TEXT DEFAULT 'free',
                    created_at TEXT NOT NULL,
                    updated_at TEXT NOT NULL,
                    last_login TEXT,
                    is_active BOOLEAN DEFAULT 1,
                    email_verified BOOLEAN DEFAULT 0
                )
            ''')
            
            # Create sessions table for active tokens
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS user_sessions (
                    id TEXT PRIMARY KEY,
                    user_id TEXT NOT NULL,
                    token_hash TEXT NOT NULL,
                    created_at TEXT NOT NULL,
                    expires_at TEXT NOT NULL,
                    is_active BOOLEAN DEFAULT 1,
                    device_info TEXT,
                    ip_address TEXT,
                    FOREIGN KEY (user_id) REFERENCES users (id)
                )
            ''')
            
            # Create user preferences table
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS user_preferences (
                    id TEXT PRIMARY KEY,
                    user_id TEXT NOT NULL,
                    preference_key TEXT NOT NULL,
                    preference_value TEXT NOT NULL,
                    created_at TEXT NOT NULL,
                    updated_at TEXT NOT NULL,
                    FOREIGN KEY (user_id) REFERENCES users (id),
                    UNIQUE(user_id, preference_key)
                )
            ''')
            
            # Create layers table for user-created layers
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS user_layers (
                    id TEXT PRIMARY KEY,
                    user_id TEXT NOT NULL,
                    name TEXT NOT NULL,
                    domain TEXT NOT NULL,
                    task_type TEXT DEFAULT 'general',
                    description TEXT DEFAULT '',
                    is_deployed BOOLEAN DEFAULT 0,
                    is_public BOOLEAN DEFAULT 0,
                    layer_config TEXT NOT NULL,
                    layer_data BLOB,
                    created_at TEXT NOT NULL,
                    updated_at TEXT NOT NULL,
                    last_trained TEXT,
                    training_status TEXT DEFAULT 'ready',
                    version TEXT DEFAULT '1.0.0',
                    file_size INTEGER DEFAULT 0,
                    FOREIGN KEY (user_id) REFERENCES users (id)
                )
            ''')
            
            # Create layer training sessions table
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS layer_training_sessions (
                    id TEXT PRIMARY KEY,
                    layer_id TEXT NOT NULL,
                    user_id TEXT NOT NULL,
                    session_type TEXT NOT NULL,
                    status TEXT DEFAULT 'running',
                    progress REAL DEFAULT 0.0,
                    started_at TEXT NOT NULL,
                    completed_at TEXT,
                    error_message TEXT,
                    training_config TEXT,
                    metrics TEXT,
                    FOREIGN KEY (layer_id) REFERENCES user_layers (id),
                    FOREIGN KEY (user_id) REFERENCES users (id)
                )
            ''')
            
            # Create layer analytics table
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS layer_analytics (
                    id TEXT PRIMARY KEY,
                    layer_id TEXT NOT NULL,
                    user_id TEXT NOT NULL,
                    query_count INTEGER DEFAULT 0,
                    last_used TEXT,
                    total_training_time REAL DEFAULT 0.0,
                    accuracy_score REAL DEFAULT 0.0,
                    performance_metrics TEXT,
                    created_at TEXT NOT NULL,
                    updated_at TEXT NOT NULL,
                    FOREIGN KEY (layer_id) REFERENCES user_layers (id),
                    FOREIGN KEY (user_id) REFERENCES users (id)
                )
            ''')
            
            # Create indexes for better performance
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)')
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON user_sessions(user_id)')
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_sessions_token ON user_sessions(token_hash)')
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_preferences_user_id ON user_preferences(user_id)')
            
            # Layer-related indexes
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_layers_user_id ON user_layers(user_id)')
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_layers_domain ON user_layers(domain)')
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_layers_deployed ON user_layers(is_deployed)')
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_layers_public ON user_layers(is_public)')
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_training_sessions_layer_id ON layer_training_sessions(layer_id)')
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_training_sessions_status ON layer_training_sessions(status)')
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_analytics_layer_id ON layer_analytics(layer_id)')
            
            conn.commit()
            conn.close()
            
            self.logger.info(f"Database initialized successfully at {self.db_path}")
            
        except Exception as e:
            self.logger.error(f"Database initialization failed: {e}")
            raise SecurityError(f"Database setup failed: {e}")
    
    def _hash_password(self, password: str, salt: bytes = None) -> tuple[str, str]:
        """Hash password with bcrypt and return (hash, salt)."""
        if salt is None:
            salt = bcrypt.gensalt()
        elif isinstance(salt, str):
            salt = salt.encode('utf-8')
            
        password_hash = bcrypt.hashpw(password.encode('utf-8'), salt)
        return password_hash.decode('utf-8'), salt.decode('utf-8')
    
    def _verify_password(self, password: str, password_hash: str) -> bool:
        """Verify password against stored hash."""
        try:
            return bcrypt.checkpw(password.encode('utf-8'), password_hash.encode('utf-8'))
        except Exception as e:
            self.logger.error(f"Password verification failed: {e}")
            return False
    
    def create_user(self, email: str, password: str, name: str) -> Dict[str, Any]:
        """Create a new user account."""
        try:
            # Check if user already exists
            if self.get_user_by_email(email):
                raise SecurityError("User with this email already exists")
            
            # Generate password hash
            password_hash, salt = self._hash_password(password)
            
            # Generate user ID
            user_id = str(uuid.uuid4())
            now = datetime.now().isoformat()
            
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            cursor.execute('''
                INSERT INTO users (id, email, name, password_hash, salt, created_at, updated_at)
                VALUES (?, ?, ?, ?, ?, ?, ?)
            ''', (user_id, email, name, password_hash, salt, now, now))
            
            conn.commit()
            conn.close()
            
            self.logger.info(f"User created successfully: {email}")
            
            return {
                "id": user_id,
                "email": email,
                "name": name,
                "subscription": "free",
                "created_at": now
            }
            
        except sqlite3.IntegrityError as e:
            if "UNIQUE constraint failed" in str(e):
                raise SecurityError("User with this email already exists")
            raise SecurityError(f"Database error: {e}")
        except Exception as e:
            self.logger.error(f"User creation failed: {e}")
            raise SecurityError(f"Failed to create user: {e}")
    
    def authenticate_user(self, email: str, password: str) -> Optional[Dict[str, Any]]:
        """Authenticate user with email and password."""
        try:
            user = self.get_user_by_email(email)
            if not user:
                return None
            
            if not user.get('is_active', True):
                return None
            
            # Verify password
            if self._verify_password(password, user['password_hash']):
                # Update last login
                self._update_last_login(user['id'])
                
                # Remove sensitive data before returning
                safe_user = {k: v for k, v in user.items() if k not in ['password_hash', 'salt']}
                return safe_user
            
            return None
            
        except Exception as e:
            self.logger.error(f"Authentication failed: {e}")
            return None
    
    def get_user_by_email(self, email: str) -> Optional[Dict[str, Any]]:
        """Get user by email address."""
        try:
            conn = sqlite3.connect(self.db_path)
            conn.row_factory = sqlite3.Row
            cursor = conn.cursor()
            
            cursor.execute('SELECT * FROM users WHERE email = ?', (email,))
            row = cursor.fetchone()
            conn.close()
            
            if row:
                return dict(row)
            return None
            
        except Exception as e:
            self.logger.error(f"Failed to get user by email: {e}")
            return None
    
    def get_user_by_id(self, user_id: str) -> Optional[Dict[str, Any]]:
        """Get user by ID."""
        try:
            conn = sqlite3.connect(self.db_path)
            conn.row_factory = sqlite3.Row
            cursor = conn.cursor()
            
            cursor.execute('SELECT * FROM users WHERE id = ?', (user_id,))
            row = cursor.fetchone()
            conn.close()
            
            if row:
                user = dict(row)
                # Remove sensitive data
                return {k: v for k, v in user.items() if k not in ['password_hash', 'salt']}
            return None
            
        except Exception as e:
            self.logger.error(f"Failed to get user by ID: {e}")
            return None
    
    def _update_last_login(self, user_id: str):
        """Update user's last login timestamp."""
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            now = datetime.now().isoformat()
            cursor.execute('UPDATE users SET last_login = ? WHERE id = ?', (now, user_id))
            
            conn.commit()
            conn.close()
            
        except Exception as e:
            self.logger.error(f"Failed to update last login: {e}")
    
    def create_session(self, user_id: str, token_hash: str, expires_at: datetime, 
                      device_info: str = None, ip_address: str = None) -> str:
        """Create a new user session."""
        try:
            session_id = str(uuid.uuid4())
            now = datetime.now().isoformat()
            
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            cursor.execute('''
                INSERT INTO user_sessions (id, user_id, token_hash, created_at, expires_at, device_info, ip_address)
                VALUES (?, ?, ?, ?, ?, ?, ?)
            ''', (session_id, user_id, token_hash, now, expires_at.isoformat(), device_info, ip_address))
            
            conn.commit()
            conn.close()
            
            return session_id
            
        except Exception as e:
            self.logger.error(f"Failed to create session: {e}")
            raise SecurityError(f"Session creation failed: {e}")
    
    def validate_session(self, token_hash: str) -> Optional[str]:
        """Validate session token and return user ID if valid."""
        try:
            conn = sqlite3.connect(self.db_path)
            conn.row_factory = sqlite3.Row
            cursor = conn.cursor()
            
            now = datetime.now().isoformat()
            cursor.execute('''
                SELECT user_id FROM user_sessions 
                WHERE token_hash = ? AND is_active = 1 AND expires_at > ?
            ''', (token_hash, now))
            
            row = cursor.fetchone()
            conn.close()
            
            if row:
                return row['user_id']
            return None
            
        except Exception as e:
            self.logger.error(f"Session validation failed: {e}")
            return None
    
    def revoke_session(self, token_hash: str):
        """Revoke a user session."""
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            cursor.execute('UPDATE user_sessions SET is_active = 0 WHERE token_hash = ?', (token_hash,))
            
            conn.commit()
            conn.close()
            
        except Exception as e:
            self.logger.error(f"Failed to revoke session: {e}")
    
    def cleanup_expired_sessions(self):
        """Clean up expired sessions."""
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            now = datetime.now().isoformat()
            cursor.execute('DELETE FROM user_sessions WHERE expires_at < ?', (now,))
            
            conn.commit()
            conn.close()
            
        except Exception as e:
            self.logger.error(f"Failed to cleanup expired sessions: {e}")
    
    def get_user_preference(self, user_id: str, key: str) -> Optional[str]:
        """Get user preference value."""
        try:
            conn = sqlite3.connect(self.db_path)
            conn.row_factory = sqlite3.Row
            cursor = conn.cursor()
            
            cursor.execute('SELECT preference_value FROM user_preferences WHERE user_id = ? AND preference_key = ?', 
                         (user_id, key))
            row = cursor.fetchone()
            conn.close()
            
            if row:
                return row['preference_value']
            return None
            
        except Exception as e:
            self.logger.error(f"Failed to get user preference: {e}")
            return None
    
    def set_user_preference(self, user_id: str, key: str, value: str):
        """Set user preference value."""
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            now = datetime.now().isoformat()
            cursor.execute('''
                INSERT OR REPLACE INTO user_preferences (id, user_id, preference_key, preference_value, created_at, updated_at)
                VALUES (?, ?, ?, ?, ?, ?)
            ''', (str(uuid.uuid4()), user_id, key, value, now, now))
            
            conn.commit()
            conn.close()
            
        except Exception as e:
            self.logger.error(f"Failed to set user preference: {e}")
    
    # ===== LAYER MANAGEMENT METHODS =====
    
    def create_layer(self, user_id: str, name: str, domain: str, task_type: str = "general", 
                    description: str = "", layer_config: str = "", layer_data: bytes = None) -> Dict[str, Any]:
        """Create a new user layer."""
        try:
            layer_id = str(uuid.uuid4())
            now = datetime.now().isoformat()
            
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            cursor.execute('''
                INSERT INTO user_layers (id, user_id, name, domain, task_type, description, 
                                       layer_config, layer_data, created_at, updated_at, file_size)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            ''', (layer_id, user_id, name, domain, task_type, description, 
                  layer_config, layer_data, now, now, len(layer_data) if layer_data else 0))
            
            # Create analytics entry
            cursor.execute('''
                INSERT INTO layer_analytics (id, layer_id, user_id, created_at, updated_at)
                VALUES (?, ?, ?, ?, ?)
            ''', (str(uuid.uuid4()), layer_id, user_id, now, now))
            
            conn.commit()
            conn.close()
            
            self.logger.info(f"Layer created successfully: {name} (ID: {layer_id})")
            
            return {
                "id": layer_id,
                "user_id": user_id,
                "name": name,
                "domain": domain,
                "task_type": task_type,
                "description": description,
                "is_deployed": False,
                "is_public": False,
                "created_at": now,
                "version": "1.0.0",
                "training_status": "ready"
            }
            
        except Exception as e:
            self.logger.error(f"Layer creation failed: {e}")
            raise SecurityError(f"Failed to create layer: {e}")
    
    def get_user_layers(self, user_id: str, include_public: bool = True) -> List[Dict[str, Any]]:
        """Get all layers for a user."""
        try:
            conn = sqlite3.connect(self.db_path)
            conn.row_factory = sqlite3.Row
            cursor = conn.cursor()
            
            if include_public:
                # Get user's own layers + deployed layers from other users
                cursor.execute('''
                    SELECT l.*, u.name as owner_name
                    FROM user_layers l
                    JOIN users u ON l.user_id = u.id
                    WHERE l.user_id = ? OR (l.is_deployed = 1 AND l.is_public = 1)
                    ORDER BY l.created_at DESC
                ''', (user_id,))
            else:
                # Get only user's own layers
                cursor.execute('''
                    SELECT l.*, u.name as owner_name
                    FROM user_layers l
                    JOIN users u ON l.user_id = u.id
                    WHERE l.user_id = ?
                    ORDER BY l.created_at DESC
                ''', (user_id,))
            
            rows = cursor.fetchall()
            conn.close()
            
            layers = []
            for row in rows:
                layer = dict(row)
                # Don't include binary data in list view
                layer.pop('layer_data', None)
                layer['isOwnedByUser'] = layer['user_id'] == user_id
                layer['isDeployed'] = bool(layer['is_deployed'])
                layers.append(layer)
            
            return layers
            
        except Exception as e:
            self.logger.error(f"Failed to get user layers: {e}")
            return []
    
    def get_public_deployed_layers(self) -> List[Dict[str, Any]]:
        """Get only public deployed layers (for anonymous users)."""
        try:
            conn = sqlite3.connect(self.db_path)
            conn.row_factory = sqlite3.Row
            cursor = conn.cursor()
            
            cursor.execute('''
                SELECT l.*, u.name as owner_name
                FROM user_layers l
                JOIN users u ON l.user_id = u.id
                WHERE l.is_deployed = 1 AND l.is_public = 1
                ORDER BY l.created_at DESC
            ''')
            
            rows = cursor.fetchall()
            conn.close()
            
            layers = []
            for row in rows:
                layer = dict(row)
                # Don't include binary data in list view
                layer.pop('layer_data', None)
                layer['isOwnedByUser'] = False  # Anonymous users don't own anything
                layer['isDeployed'] = True  # All results are deployed
                layers.append(layer)
            
            return layers
            
        except Exception as e:
            self.logger.error(f"Failed to get public deployed layers: {e}")
            return []
    
    def get_layer_by_id(self, layer_id: str, user_id: str = None) -> Optional[Dict[str, Any]]:
        """Get a specific layer by ID."""
        try:
            conn = sqlite3.connect(self.db_path)
            conn.row_factory = sqlite3.Row
            cursor = conn.cursor()
            
            cursor.execute('''
                SELECT l.*, u.name as owner_name
                FROM user_layers l
                JOIN users u ON l.user_id = u.id
                WHERE l.id = ?
            ''', (layer_id,))
            
            row = cursor.fetchone()
            conn.close()
            
            if row:
                layer = dict(row)
                if user_id:
                    layer['isOwnedByUser'] = layer['user_id'] == user_id
                    layer['isDeployed'] = bool(layer['is_deployed'])
                    # Only return layer data if user owns it or it's deployed
                    if not (layer['user_id'] == user_id or layer['is_deployed']):
                        layer.pop('layer_data', None)
                return layer
            return None
            
        except Exception as e:
            self.logger.error(f"Failed to get layer by ID: {e}")
            return None
    
    def update_layer(self, layer_id: str, user_id: str, updates: Dict[str, Any]) -> bool:
        """Update a layer (only if user owns it)."""
        try:
            # Verify ownership
            layer = self.get_layer_by_id(layer_id, user_id)
            if not layer or layer['user_id'] != user_id:
                return False
            
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # Build update query dynamically
            allowed_fields = ['name', 'description', 'is_deployed', 'is_public', 'layer_config', 
                            'layer_data', 'training_status', 'last_trained', 'version']
            set_clauses = []
            values = []
            
            for field, value in updates.items():
                if field in allowed_fields:
                    set_clauses.append(f"{field} = ?")
                    values.append(value)
            
            if set_clauses:
                set_clauses.append("updated_at = ?")
                values.append(datetime.now().isoformat())
                values.append(layer_id)
                
                query = f"UPDATE user_layers SET {', '.join(set_clauses)} WHERE id = ?"
                cursor.execute(query, values)
                
                conn.commit()
            
            conn.close()
            return True
            
        except Exception as e:
            self.logger.error(f"Failed to update layer: {e}")
            return False
    
    def delete_layer(self, layer_id: str, user_id: str) -> bool:
        """Delete a layer (only if user owns it)."""
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            # Delete layer (will cascade to related tables due to foreign keys)
            cursor.execute('DELETE FROM user_layers WHERE id = ? AND user_id = ?', (layer_id, user_id))
            cursor.execute('DELETE FROM layer_training_sessions WHERE layer_id = ?', (layer_id,))
            cursor.execute('DELETE FROM layer_analytics WHERE layer_id = ?', (layer_id,))
            
            rows_affected = cursor.rowcount
            conn.commit()
            conn.close()
            
            if rows_affected > 0:
                self.logger.info(f"Layer deleted: {layer_id}")
                return True
            return False
            
        except Exception as e:
            self.logger.error(f"Failed to delete layer: {e}")
            return False
    
    def deploy_layer(self, layer_id: str, user_id: str, is_deployed: bool = True, is_public: bool = True) -> bool:
        """Deploy or undeploy a layer."""
        return self.update_layer(layer_id, user_id, {
            'is_deployed': is_deployed,
            'is_public': is_public
        })
    
    def create_training_session(self, layer_id: str, user_id: str, session_type: str, 
                              training_config: str = "") -> str:
        """Create a new training session."""
        try:
            session_id = str(uuid.uuid4())
            now = datetime.now().isoformat()
            
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            cursor.execute('''
                INSERT INTO layer_training_sessions (id, layer_id, user_id, session_type, 
                                                   started_at, training_config)
                VALUES (?, ?, ?, ?, ?, ?)
            ''', (session_id, layer_id, user_id, session_type, now, training_config))
            
            conn.commit()
            conn.close()
            
            return session_id
            
        except Exception as e:
            self.logger.error(f"Failed to create training session: {e}")
            raise SecurityError(f"Training session creation failed: {e}")
    
    def update_training_session(self, session_id: str, updates: Dict[str, Any]) -> bool:
        """Update a training session."""
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            allowed_fields = ['status', 'progress', 'completed_at', 'error_message', 'metrics']
            set_clauses = []
            values = []
            
            for field, value in updates.items():
                if field in allowed_fields:
                    set_clauses.append(f"{field} = ?")
                    values.append(value)
            
            if set_clauses:
                values.append(session_id)
                query = f"UPDATE layer_training_sessions SET {', '.join(set_clauses)} WHERE id = ?"
                cursor.execute(query, values)
                conn.commit()
            
            conn.close()
            return True
            
        except Exception as e:
            self.logger.error(f"Failed to update training session: {e}")
            return False
    
    def get_active_training_sessions(self, user_id: str = None) -> List[Dict[str, Any]]:
        """Get active training sessions."""
        try:
            conn = sqlite3.connect(self.db_path)
            conn.row_factory = sqlite3.Row
            cursor = conn.cursor()
            
            if user_id:
                cursor.execute('''
                    SELECT ts.*, l.name as layer_name
                    FROM layer_training_sessions ts
                    JOIN user_layers l ON ts.layer_id = l.id
                    WHERE ts.user_id = ? AND ts.status = 'running'
                    ORDER BY ts.started_at DESC
                ''', (user_id,))
            else:
                cursor.execute('''
                    SELECT ts.*, l.name as layer_name, u.name as user_name
                    FROM layer_training_sessions ts
                    JOIN user_layers l ON ts.layer_id = l.id
                    JOIN users u ON ts.user_id = u.id
                    WHERE ts.status = 'running'
                    ORDER BY ts.started_at DESC
                ''')
            
            rows = cursor.fetchall()
            conn.close()
            
            return [dict(row) for row in rows]
            
        except Exception as e:
            self.logger.error(f"Failed to get training sessions: {e}")
            return []
    
    def update_layer_analytics(self, layer_id: str, updates: Dict[str, Any]) -> bool:
        """Update layer analytics."""
        try:
            conn = sqlite3.connect(self.db_path)
            cursor = conn.cursor()
            
            allowed_fields = ['query_count', 'last_used', 'total_training_time', 
                            'accuracy_score', 'performance_metrics']
            set_clauses = []
            values = []
            
            for field, value in updates.items():
                if field in allowed_fields:
                    set_clauses.append(f"{field} = ?")
                    values.append(value)
            
            if set_clauses:
                set_clauses.append("updated_at = ?")
                values.append(datetime.now().isoformat())
                values.append(layer_id)
                
                query = f"UPDATE layer_analytics SET {', '.join(set_clauses)} WHERE layer_id = ?"
                cursor.execute(query, values)
                conn.commit()
            
            conn.close()
            return True
            
        except Exception as e:
            self.logger.error(f"Failed to update layer analytics: {e}")
            return False


# Global database instance
_db_manager = None

def get_database_manager() -> DatabaseManager:
    """Get the global database manager instance."""
    global _db_manager
    if _db_manager is None:
        _db_manager = DatabaseManager()
    return _db_manager 