#!/usr/bin/env python3
"""
database.py - Módulo de conexão e operações com banco de dados

Este módulo gerencia conexões com banco de dados e operações CRUD básicas.
"""

import sqlite3
import logging
from typing import Optional, List, Dict, Any, Tuple
from contextlib import contextmanager

logger = logging.getLogger(__name__)

class DatabaseManager:
    """
    Gerenciador de conexões e operações com banco de dados SQLite.
    """
    
    def __init__(self, db_path: str):
        """
        Inicializa o gerenciador de banco de dados.
        
        Args:
            db_path (str): Caminho para o arquivo do banco de dados
        """
        self.db_path = db_path
        self.init_database()
    
    def init_database(self) -> None:
        """
        Inicializa o banco de dados com tabelas básicas.
        """
        with self.get_connection() as conn:
            cursor = conn.cursor()
            
            # Criar tabela de usuários
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS users (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    email TEXT UNIQUE NOT NULL,
                    password_hash TEXT NOT NULL,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
            """)
            
            # Criar tabela de logs
            cursor.execute("""
                CREATE TABLE IF NOT EXISTS logs (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    level TEXT NOT NULL,
                    message TEXT NOT NULL,
                    timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
            """)
            
            conn.commit()
            logger.info("Banco de dados inicializado com sucesso")
    
    @contextmanager
    def get_connection(self):
        """
        Context manager para conexões com o banco de dados.
        
        Yields:
            sqlite3.Connection: Conexão com o banco
        """
        conn = None
        try:
            conn = sqlite3.connect(self.db_path)
            conn.row_factory = sqlite3.Row  # Permite acesso por nome da coluna
            yield conn
        except Exception as e:
            if conn:
                conn.rollback()
            logger.error(f"Erro na conexão com banco de dados: {e}")
            raise
        finally:
            if conn:
                conn.close()
    
    def create_user(self, email: str, password_hash: str) -> Optional[int]:
        """
        Cria um novo usuário no banco de dados.
        
        Args:
            email (str): Email do usuário
            password_hash (str): Hash da senha
            
        Returns:
            Optional[int]: ID do usuário criado ou None se erro
        """
        try:
            with self.get_connection() as conn:
                cursor = conn.cursor()
                cursor.execute(
                    "INSERT INTO users (email, password_hash) VALUES (?, ?)",
                    (email, password_hash)
                )
                conn.commit()
                return cursor.lastrowid
        except sqlite3.IntegrityError:
            logger.warning(f"Usuário com email {email} já existe")
            return None
        except Exception as e:
            logger.error(f"Erro ao criar usuário: {e}")
            return None
    
    def get_user_by_email(self, email: str) -> Optional[Dict[str, Any]]:
        """
        Busca usuário por email.
        
        Args:
            email (str): Email do usuário
            
        Returns:
            Optional[Dict[str, Any]]: Dados do usuário ou None se não encontrado
        """
        try:
            with self.get_connection() as conn:
                cursor = conn.cursor()
                cursor.execute(
                    "SELECT * FROM users WHERE email = ?",
                    (email,)
                )
                row = cursor.fetchone()
                return dict(row) if row else None
        except Exception as e:
            logger.error(f"Erro ao buscar usuário: {e}")
            return None
    
    def update_user_password(self, user_id: int, new_password_hash: str) -> bool:
        """
        Atualiza senha de um usuário.
        
        Args:
            user_id (int): ID do usuário
            new_password_hash (str): Novo hash da senha
            
        Returns:
            bool: True se atualizado com sucesso, False caso contrário
        """
        try:
            with self.get_connection() as conn:
                cursor = conn.cursor()
                cursor.execute(
                    "UPDATE users SET password_hash = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?",
                    (new_password_hash, user_id)
                )
                conn.commit()
                return cursor.rowcount > 0
        except Exception as e:
            logger.error(f"Erro ao atualizar senha: {e}")
            return False
    
    def log_message(self, level: str, message: str) -> bool:
        """
        Registra uma mensagem de log no banco de dados.
        
        Args:
            level (str): Nível do log (INFO, WARNING, ERROR)
            message (str): Mensagem do log
            
        Returns:
            bool: True se registrado com sucesso, False caso contrário
        """
        try:
            with self.get_connection() as conn:
                cursor = conn.cursor()
                cursor.execute(
                    "INSERT INTO logs (level, message) VALUES (?, ?)",
                    (level, message)
                )
                conn.commit()
                return True
        except Exception as e:
            logger.error(f"Erro ao registrar log: {e}")
            return False
    
    def get_recent_logs(self, limit: int = 100) -> List[Dict[str, Any]]:
        """
        Busca logs recentes do banco de dados.
        
        Args:
            limit (int): Número máximo de logs a retornar
            
        Returns:
            List[Dict[str, Any]]: Lista de logs
        """
        try:
            with self.get_connection() as conn:
                cursor = conn.cursor()
                cursor.execute(
                    "SELECT * FROM logs ORDER BY timestamp DESC LIMIT ?",
                    (limit,)
                )
                rows = cursor.fetchall()
                return [dict(row) for row in rows]
        except Exception as e:
            logger.error(f"Erro ao buscar logs: {e}")
            return []
    
    def execute_query(self, query: str, params: Tuple = ()) -> List[Dict[str, Any]]:
        """
        Executa uma query SQL personalizada.
        
        Args:
            query (str): Query SQL
            params (Tuple): Parâmetros da query
            
        Returns:
            List[Dict[str, Any]]: Resultados da query
        """
        try:
            with self.get_connection() as conn:
                cursor = conn.cursor()
                cursor.execute(query, params)
                rows = cursor.fetchall()
                return [dict(row) for row in rows]
        except Exception as e:
            logger.error(f"Erro ao executar query: {e}")
            return []