import sqlite3
import mysql.connector
import json
import time
from mysql.connector import Error as MySQLError
from botdiscord.config import get_db_config, get_db_type

_connection = None
MAX_CONNECTION_RETRIES = 30
CONNECTION_RETRY_DELAY = 2

def get_connection():
    global _connection
    db_type = get_db_type()
    
    if db_type == "mysql":
        db_config = get_db_config()
        
        if _connection is None:
            for attempt in range(1, MAX_CONNECTION_RETRIES + 1):
                try:
                    _connection = mysql.connector.connect(
                        host=db_config.get("host"),
                        port=db_config.get("port"),
                        user=db_config.get("user"),
                        password=db_config.get("password"),
                        database=db_config.get("name"),
                        consume_results=True,
                        connection_timeout=10,
                        autocommit=True
                    )
                    print(f"[DB] MySQL conectado exitosamente")
                    break
                except MySQLError as e:
                    if attempt < MAX_CONNECTION_RETRIES:
                        print(f"[DB] Intento {attempt}/{MAX_CONNECTION_RETRIES}: MySQL no disponible, reintentando en {CONNECTION_RETRY_DELAY}s...")
                        time.sleep(CONNECTION_RETRY_DELAY)
                        _connection = None
                    else:
                        print(f"[DB] CRITICAL: No se pudo conectar a MySQL después de {MAX_CONNECTION_RETRIES} intentos")
                        raise
        
        try:
            _connection.ping(reconnect=True, attempts=3, delay=1)
        except MySQLError:
            for attempt in range(1, 6):
                try:
                    print(f"[DB] Reconectando a MySQL (intento {attempt}/5)...")
                    _connection = mysql.connector.connect(
                        host=db_config.get("host"),
                        port=db_config.get("port"),
                        user=db_config.get("user"),
                        password=db_config.get("password"),
                        database=db_config.get("name"),
                        consume_results=True,
                        connection_timeout=10,
                        autocommit=True
                    )
                    print(f"[DB] MySQL reconectado exitosamente")
                    break
                except MySQLError as e:
                    if attempt < 5:
                        time.sleep(2)
                        _connection = None
                    else:
                        print(f"[DB] CRITICAL: MySQL reconnection failed: {e}")
                        raise
                
        return _connection
    else:
        import os
        from botdiscord.config import get_db_path
        db_path = get_db_path()
        db_dir = os.path.dirname(db_path)
        if db_dir and not os.path.exists(db_dir):
            os.makedirs(db_dir, exist_ok=True)
        return sqlite3.connect(db_path, isolation_level=None)

def close_connection():
    global _connection
    if _connection and _connection.is_connected():
        _connection.close()
        _connection = None

def _execute_query(query, params=None, fetch=False):
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        try:
            cursor.execute(query, params or ())
            if fetch:
                result = cursor.fetchall()
            else:
                conn.commit()
                result = cursor.lastrowid
            return result
        finally:
            cursor.close()
    else:
        conn = get_connection()
        cursor = conn.cursor()
        try:
            cursor.execute(query, params or ())
            if fetch:
                result = cursor.fetchall()
            else:
                conn.commit()
                result = cursor.lastrowid
            return result
        finally:
            cursor.close()

def init_db():
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute('''CREATE TABLE IF NOT EXISTS guild_languages
                     (guild_id BIGINT NOT NULL, lang_code VARCHAR(10) NOT NULL, 
                      PRIMARY KEY (guild_id, lang_code)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
        cursor.execute('''CREATE TABLE IF NOT EXISTS bot_config
                     (`key` VARCHAR(255) NOT NULL, value TEXT, 
                      PRIMARY KEY (`key`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
        cursor.execute('''CREATE TABLE IF NOT EXISTS available_languages
                     (code VARCHAR(10) NOT NULL, name VARCHAR(100) NOT NULL, flag VARCHAR(20),
                      PRIMARY KEY (code)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
        cursor.execute('''CREATE TABLE IF NOT EXISTS bot_languages
                     (bot_type VARCHAR(50) NOT NULL, lang_code VARCHAR(10) NOT NULL, 
                      PRIMARY KEY (bot_type, lang_code)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
        
        # Nuevas tablas para caché y persistencia
        cursor.execute('''CREATE TABLE IF NOT EXISTS messages
                     (message_id BIGINT PRIMARY KEY, 
                      guild_id BIGINT, 
                      author_id BIGINT, 
                      content TEXT NOT NULL, 
                      mentions_map JSON, 
                      bot_type ENUM('discord', 'telegram') NOT NULL,
                      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
        
        cursor.execute('''CREATE TABLE IF NOT EXISTS translations
                     (id INT AUTO_INCREMENT PRIMARY KEY,
                      message_id BIGINT NOT NULL,
                      target_lang VARCHAR(10) NOT NULL,
                      translated_text TEXT NOT NULL,
                      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                      FOREIGN KEY (message_id) REFERENCES messages(message_id) ON DELETE CASCADE,
                      UNIQUE KEY idx_msg_lang (message_id, target_lang)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
        # Tabla para traducciones de la interfaz web
        cursor.execute('''CREATE TABLE IF NOT EXISTS ui_translations
                     (id INT AUTO_INCREMENT PRIMARY KEY,
                      text_hash VARCHAR(64) NOT NULL,
                      original_text TEXT NOT NULL,
                      target_lang VARCHAR(10) NOT NULL,
                      translated_text TEXT NOT NULL,
                      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                      UNIQUE KEY idx_ui_hash_lang (text_hash, target_lang)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')

        # Migración automática: Añadir text_hash si no existe
        try:
            cursor.execute("SHOW COLUMNS FROM ui_translations LIKE 'text_hash'")
            if not cursor.fetchone():
                print("Migrating ui_translations: Adding text_hash column...")
                # Primero borramos el índice viejo si existe (basado en el código anterior)
                try:
                    cursor.execute("ALTER TABLE ui_translations DROP INDEX idx_ui_lang")
                except: pass
                # Añadimos la columna y el nuevo índice
                cursor.execute("ALTER TABLE ui_translations ADD COLUMN text_hash VARCHAR(64) NOT NULL AFTER id")
                cursor.execute("ALTER TABLE ui_translations ADD UNIQUE KEY idx_ui_hash_lang (text_hash, target_lang)")
                # Limpiamos la tabla para evitar conflictos de hash con datos viejos
                cursor.execute("DELETE FROM ui_translations")
        except Exception as e:
            print(f"Migration warning: {e}")

        conn.commit()
        # Tabla para administradores del panel web
        cursor.execute('''CREATE TABLE IF NOT EXISTS admins
                     (id INT AUTO_INCREMENT PRIMARY KEY,
                      username VARCHAR(50) NOT NULL UNIQUE,
                      password_hash VARCHAR(255) NOT NULL,
                      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
        
        cursor.execute('''CREATE TABLE IF NOT EXISTS welcome_messages
                     (guild_id BIGINT PRIMARY KEY,
                      channel_id BIGINT NOT NULL,
                      message_content TEXT NOT NULL,
                      enabled BOOLEAN DEFAULT TRUE,
                      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                      updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
        
        cursor.execute('''CREATE TABLE IF NOT EXISTS discord_servers
                     (server_id BIGINT NOT NULL PRIMARY KEY, 
                      server_name VARCHAR(255) NOT NULL,
                      added_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
        
        cursor.execute('''CREATE TABLE IF NOT EXISTS discord_channels
                     (channel_id BIGINT NOT NULL PRIMARY KEY,
                      channel_name VARCHAR(255) NOT NULL,
                      server_id BIGINT NOT NULL,
                      is_active BOOLEAN DEFAULT TRUE,
                      added_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                      FOREIGN KEY (server_id) REFERENCES discord_servers(server_id) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4''')
        
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute('''CREATE TABLE IF NOT EXISTS guild_languages
                     (guild_id INTEGER, lang_code TEXT, PRIMARY KEY (guild_id, lang_code))''')
        c.execute('''CREATE TABLE IF NOT EXISTS bot_config
                     (key TEXT PRIMARY KEY, value TEXT)''')
        c.execute('''CREATE TABLE IF NOT EXISTS available_languages
                     (code TEXT PRIMARY KEY, name TEXT, flag TEXT)''')
        c.execute('''CREATE TABLE IF NOT EXISTS bot_languages
                     (bot_type TEXT, lang_code TEXT, PRIMARY KEY (bot_type, lang_code))''')
        
        # SQLite equivalents
        c.execute('''CREATE TABLE IF NOT EXISTS messages
                     (message_id INTEGER PRIMARY KEY, 
                      guild_id INTEGER, 
                      author_id INTEGER, 
                      content TEXT NOT NULL, 
                      mentions_map TEXT, 
                      bot_type TEXT NOT NULL,
                      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)''')
        
        c.execute('''CREATE TABLE IF NOT EXISTS translations
                     (id INTEGER PRIMARY KEY AUTOINCREMENT,
                      message_id INTEGER NOT NULL,
                      target_lang TEXT NOT NULL,
                      translated_text TEXT NOT NULL,
                      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                      UNIQUE(message_id, target_lang))''')
        
        # SQLite equivalent for UI translations
        c.execute('''CREATE TABLE IF NOT EXISTS ui_translations
                     (id INTEGER PRIMARY KEY AUTOINCREMENT,
                      original_text TEXT NOT NULL,
                      target_lang TEXT NOT NULL,
                      translated_text TEXT NOT NULL,
                      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                      UNIQUE(original_text, target_lang))''')
        
        # SQLite equivalent for admins
        c.execute('''CREATE TABLE IF NOT EXISTS admins
                     (id INTEGER PRIMARY KEY AUTOINCREMENT,
                      username TEXT NOT NULL UNIQUE,
                      password_hash TEXT NOT NULL,
                      created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)''')
        
        c.execute('''CREATE TABLE IF NOT EXISTS welcome_messages
                     (guild_id INTEGER PRIMARY KEY,
                      channel_id INTEGER NOT NULL,
                      message_content TEXT NOT NULL,
                      enabled INTEGER DEFAULT 1)''')
        
        c.execute('''CREATE TABLE IF NOT EXISTS discord_servers
                     (server_id INTEGER PRIMARY KEY, 
                      server_name TEXT NOT NULL,
                      added_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)''')
        
        c.execute('''CREATE TABLE IF NOT EXISTS discord_channels
                     (channel_id INTEGER PRIMARY KEY,
                      channel_name TEXT NOT NULL,
                      server_id INTEGER NOT NULL,
                      is_active INTEGER DEFAULT 1,
                      added_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                      FOREIGN KEY (server_id) REFERENCES discord_servers(server_id))''')
        
        conn.commit()
        conn.close()

def set_available_languages(languages: list):
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("DELETE FROM available_languages")
        for lang in languages:
            cursor.execute("INSERT INTO available_languages (code, name, flag) VALUES (%s, %s, %s)", 
                          (lang.get("code"), lang.get("name"), lang.get("flag", "")))
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("DELETE FROM available_languages")
        for lang in languages:
            c.execute("INSERT OR REPLACE INTO available_languages (code, name, flag) VALUES (?, ?, ?)", 
                      (lang.get("code"), lang.get("name"), lang.get("flag", "")))
        conn.commit()
        conn.close()

def get_available_languages() -> list:
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("SELECT code, name, flag FROM available_languages ORDER BY name")
        rows = cursor.fetchall()
        cursor.close()
        return [{"code": row[0], "name": row[1], "flag": row[2] or ""} for row in rows]
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("SELECT code, name, flag FROM available_languages ORDER BY name")
        langs = [{"code": row[0], "name": row[1], "flag": row[2] or ""} for row in c.fetchall()]
        conn.close()
        return langs

def set_bot_languages(bot_type: str, lang_codes: list):
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("DELETE FROM bot_languages WHERE bot_type = %s", (bot_type,))
        for code in lang_codes:
            cursor.execute("INSERT INTO bot_languages (bot_type, lang_code) VALUES (%s, %s)", 
                          (bot_type, code))
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("DELETE FROM bot_languages WHERE bot_type = ?", (bot_type,))
        for code in lang_codes:
            c.execute("INSERT INTO bot_languages (bot_type, lang_code) VALUES (?, ?)", 
                      (bot_type, code))
        conn.commit()
        conn.close()

def get_bot_languages(bot_type: str) -> list:
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("SELECT lang_code FROM bot_languages WHERE bot_type = %s", (bot_type,))
        rows = cursor.fetchall()
        cursor.close()
        return [row[0] for row in rows]
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("SELECT lang_code FROM bot_languages WHERE bot_type = ?", (bot_type,))
        langs = [row[0] for row in c.fetchall()]
        conn.close()
        return langs

def get_active_languages(guild_id: int) -> list:
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("SELECT lang_code FROM guild_languages WHERE guild_id = %s", (guild_id,))
        rows = cursor.fetchall()
        cursor.close()
        return [row[0] for row in rows]
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("SELECT lang_code FROM guild_languages WHERE guild_id = ?", (guild_id,))
        langs = [row[0] for row in c.fetchall()]
        conn.close()
        return langs

def set_active_languages(guild_id: int, lang_codes: list):
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("DELETE FROM guild_languages WHERE guild_id = %s", (guild_id,))
        for code in lang_codes:
            cursor.execute("INSERT INTO guild_languages (guild_id, lang_code) VALUES (%s, %s)", 
                          (guild_id, code))
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("DELETE FROM guild_languages WHERE guild_id = ?", (guild_id,))
        for code in lang_codes:
            c.execute("INSERT INTO guild_languages (guild_id, lang_code) VALUES (?, ?)", (guild_id, code))
        conn.commit()
        conn.close()

def get_config_value(key: str) -> str:
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("SELECT value FROM bot_config WHERE `key` = %s", (key,))
        row = cursor.fetchone()
        cursor.close()
        return row[0] if row else None
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("SELECT value FROM bot_config WHERE key = ?", (key,))
        row = c.fetchone()
        conn.close()
        return row[0] if row else None

def set_config_value(key: str, value: str):
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("INSERT INTO bot_config (`key`, value) VALUES (%s, %s) ON DUPLICATE KEY UPDATE value = %s", 
                      (key, value, value))
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("INSERT OR REPLACE INTO bot_config (key, value) VALUES (?, ?)", (key, value))
        conn.commit()
        conn.close()

def save_message(message_id: int, guild_id: int, author_id: int, content: str, mentions_map: dict, bot_type: str):
    db_type = get_db_type()
    mentions_json = json.dumps(mentions_map)
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        query = """INSERT INTO messages (message_id, guild_id, author_id, content, mentions_map, bot_type) 
                   VALUES (%s, %s, %s, %s, %s, %s) 
                   ON DUPLICATE KEY UPDATE content = %s, mentions_map = %s"""
        cursor.execute(query, (message_id, guild_id, author_id, content, mentions_json, bot_type, content, mentions_json))
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("INSERT OR REPLACE INTO messages (message_id, guild_id, author_id, content, mentions_map, bot_type) VALUES (?, ?, ?, ?, ?, ?)", 
                  (message_id, guild_id, author_id, content, mentions_json, bot_type))
        conn.commit()
        conn.close()

def get_message(message_id: int):
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT content, mentions_map, bot_type FROM messages WHERE message_id = %s", (message_id,))
        row = cursor.fetchone()
        cursor.close()
        if row:
            if row['mentions_map']:
                row['mentions_map'] = json.loads(row['mentions_map'])
            return row
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("SELECT content, mentions_map, bot_type FROM messages WHERE message_id = ?", (message_id,))
        row = c.fetchone()
        conn.close()
        if row:
            return {
                'content': row[0],
                'mentions_map': json.loads(row[1]) if row[1] else {},
                'bot_type': row[2]
            }
    return None

def save_translation(message_id: int, target_lang: str, translated_text: str):
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        query = "INSERT INTO translations (message_id, target_lang, translated_text) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE translated_text = %s"
        cursor.execute(query, (message_id, target_lang, translated_text, translated_text))
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("INSERT OR REPLACE INTO translations (message_id, target_lang, translated_text) VALUES (?, ?, ?)", 
                  (message_id, target_lang, translated_text))
        conn.commit()
        conn.close()

def get_cached_translation(message_id: int, target_lang: str) -> str:
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("SELECT translated_text FROM translations WHERE message_id = %s AND target_lang = %s", (message_id, target_lang))
        row = cursor.fetchone()
        cursor.close()
        return row[0] if row else None
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("SELECT translated_text FROM translations WHERE message_id = ? AND target_lang = ?", (message_id, target_lang))
        row = c.fetchone()
        conn.close()
        return row[0] if row else None

import hashlib

def _normalize_text(text: str) -> str:
    """Normaliza el texto para que el caché sea consistente."""
    if not text: return ""
    # Quitar espacios en extremos, normalizar saltos de línea y quitar espacios dobles
    text = text.strip().replace('\r\n', '\n')
    return " ".join(text.split())

def _get_text_hash(text: str) -> str:
    """Genera un hash único para el texto normalizado."""
    norm = _normalize_text(text)
    return hashlib.sha256(norm.encode('utf-8')).hexdigest()

def get_ui_translation(text: str, target_lang: str) -> str:
    db_type = get_db_type()
    text_hash = _get_text_hash(text)
    try:
        if db_type == "mysql":
            conn = get_connection()
            cursor = conn.cursor()
            cursor.execute("SELECT translated_text FROM ui_translations WHERE text_hash = %s AND target_lang = %s", (text_hash, target_lang))
            row = cursor.fetchone()
            cursor.close()
            return row[0] if row else None
        else:
            conn = get_connection()
            c = conn.cursor()
            c.execute("SELECT translated_text FROM ui_translations WHERE text_hash = ? AND target_lang = ?", (text_hash, target_lang))
            row = c.fetchone()
            conn.close()
            return row[0] if row else None
    except Exception as e:
        print(f"Database error in get_ui_translation: {e}")
        return None

def save_ui_translation(text: str, target_lang: str, translated_text: str):
    db_type = get_db_type()
    text_hash = _get_text_hash(text)
    try:
        if db_type == "mysql":
            conn = get_connection()
            cursor = conn.cursor()
            query = """INSERT INTO ui_translations (text_hash, original_text, target_lang, translated_text) 
                       VALUES (%s, %s, %s, %s) 
                       ON DUPLICATE KEY UPDATE translated_text = %s"""
            cursor.execute(query, (text_hash, text, target_lang, translated_text, translated_text))
            conn.commit()
            cursor.close()
        else:
            conn = get_connection()
            c = conn.cursor()
            c.execute("INSERT OR REPLACE INTO ui_translations (text_hash, original_text, target_lang, translated_text) VALUES (?, ?, ?, ?)", 
                      (text_hash, text, target_lang, translated_text))
            conn.commit()
            conn.close()
    except Exception as e:
        print(f"Database error in save_ui_translation: {e}")

# Funciones para administradores
def get_admins():
    db_type = get_db_type()
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT id, username, created_at FROM admins ORDER BY username")
        rows = cursor.fetchall()
        cursor.close()
        return rows
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("SELECT id, username, created_at FROM admins ORDER BY username")
        rows = [{"id": r[0], "username": r[1], "created_at": r[2]} for r in c.fetchall()]
        conn.close()
        return rows

def get_admin_by_username(username: str):
    db_type = get_db_type()
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT * FROM admins WHERE username = %s", (username,))
        row = cursor.fetchone()
        cursor.close()
        return row
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("SELECT id, username, password_hash, created_at FROM admins WHERE username = ?", (username,))
        row = c.fetchone()
        conn.close()
        if row:
            return {"id": row[0], "username": row[1], "password_hash": row[2], "created_at": row[3]}
        return None

def add_admin(username: str, password_hash: str):
    db_type = get_db_type()
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("INSERT INTO admins (username, password_hash) VALUES (%s, %s)", (username, password_hash))
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("INSERT INTO admins (username, password_hash) VALUES (?, ?)", (username, password_hash))
        conn.commit()
        conn.close()

def delete_admin(admin_id: int):
    db_type = get_db_type()
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("DELETE FROM admins WHERE id = %s", (admin_id,))
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("DELETE FROM admins WHERE id = ?", (admin_id,))
        conn.commit()
        conn.close()

def update_admin_password(admin_id: int, password_hash: str):
    db_type = get_db_type()
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("UPDATE admins SET password_hash = %s WHERE id = %s", (password_hash, admin_id))
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("UPDATE admins SET password_hash = ? WHERE id = ?", (password_hash, admin_id))
        conn.commit()
        conn.close()

def save_welcome_message(guild_id: int, channel_id: int, message_content: str, enabled: bool = True):
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        query = """INSERT INTO welcome_messages (guild_id, channel_id, message_content, enabled) 
                   VALUES (%s, %s, %s, %s) 
                   ON DUPLICATE KEY UPDATE channel_id = %s, message_content = %s, enabled = %s"""
        cursor.execute(query, (guild_id, channel_id, message_content, enabled, channel_id, message_content, enabled))
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("""INSERT OR REPLACE INTO welcome_messages (guild_id, channel_id, message_content, enabled) 
                     VALUES (?, ?, ?, ?)""", (guild_id, channel_id, message_content, 1 if enabled else 0))
        conn.commit()
        conn.close()

def get_welcome_message(guild_id: int):
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT channel_id, message_content, enabled FROM welcome_messages WHERE guild_id = %s", (guild_id,))
        row = cursor.fetchone()
        cursor.close()
        if row:
            return {
                'channel_id': int(row['channel_id']) if row['channel_id'] else 0,
                'message_content': row['message_content'] or '',
                'enabled': bool(row['enabled'])
            }
        return None
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("SELECT channel_id, message_content, enabled FROM welcome_messages WHERE guild_id = ?", (guild_id,))
        row = c.fetchone()
        conn.close()
        if row:
            return {
                "channel_id": int(row[0]) if row[0] else 0,
                "message_content": row[1] or '',
                "enabled": bool(row[2])
            }
        return None

def get_all_welcome_configs():
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT guild_id, channel_id, message_content, enabled FROM welcome_messages")
        rows = cursor.fetchall()
        cursor.close()
        result = []
        for row in rows:
            result.append({
                'guild_id': int(row['guild_id']) if row['guild_id'] else 0,
                'channel_id': int(row['channel_id']) if row['channel_id'] else 0,
                'message_content': row['message_content'] or '',
                'enabled': bool(row['enabled'])
            })
        return result
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("SELECT guild_id, channel_id, message_content, enabled FROM welcome_messages")
        rows = [{"guild_id": r[0], "channel_id": r[1], "message_content": r[2], "enabled": bool(r[3])} for r in c.fetchall()]
        conn.close()
        return rows

def delete_welcome_message(guild_id: int):
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("DELETE FROM welcome_messages WHERE guild_id = %s", (guild_id,))
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("DELETE FROM welcome_messages WHERE guild_id = ?", (guild_id,))
        conn.commit()
        conn.close()

# Funciones para gestión de servidores y canales de Discord
def sync_discord_servers(servers: list):
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        for server in servers:
            server_id = server.get('id')
            server_name = server.get('name', '')
            cursor.execute("""INSERT INTO discord_servers (server_id, server_name) 
                             VALUES (%s, %s) 
                             ON DUPLICATE KEY UPDATE server_name = %s""", 
                          (server_id, server_name, server_name))
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        for server in servers:
            server_id = server.get('id')
            server_name = server.get('name', '')
            c.execute("""INSERT OR REPLACE INTO discord_servers (server_id, server_name) 
                         VALUES (?, ?)""", (server_id, server_name))
        conn.commit()
        conn.close()

def get_discord_servers() -> list:
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT server_id, server_name, added_at FROM discord_servers ORDER BY server_name")
        rows = cursor.fetchall()
        cursor.close()
        return rows
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("SELECT server_id, server_name, added_at FROM discord_servers ORDER BY server_name")
        rows = [{"server_id": r[0], "server_name": r[1], "added_at": r[2]} for r in c.fetchall()]
        conn.close()
        return rows

def sync_discord_channels(server_id: int, channels: list):
    db_type = get_db_type()
    
    try:
        if db_type == "mysql":
            conn = get_connection()
            cursor = conn.cursor()
            for channel in channels:
                channel_id = channel.get('id')
                channel_name = channel.get('name', '')
                cursor.execute("""INSERT INTO discord_channels (channel_id, channel_name, server_id) 
                                 VALUES (%s, %s, %s) 
                                 ON DUPLICATE KEY UPDATE channel_name = %s, server_id = %s""", 
                              (channel_id, channel_name, server_id, channel_name, server_id))
            conn.commit()
            cursor.close()
        else:
            conn = get_connection()
            c = conn.cursor()
            for channel in channels:
                channel_id = channel.get('id')
                channel_name = channel.get('name', '')
                c.execute("""INSERT OR REPLACE INTO discord_channels (channel_id, channel_name, server_id) 
                             VALUES (?, ?, ?)""", (channel_id, channel_name, server_id))
            conn.commit()
            conn.close()
        
        # Limpiar todo el cache de canales después de sincronizar
        clear_channel_cache()
        print(f"[DB] Canales sincronizados para servidor {server_id}, cache limpiado")
        
    except Exception as e:
        print(f"[DB] Error sincronizando canales del servidor {server_id}: {e}")
        raise

def get_discord_channels(server_id: int = None) -> list:
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor(dictionary=True)
        if server_id:
            cursor.execute("SELECT channel_id, channel_name, server_id, is_active, added_at FROM discord_channels WHERE server_id = %s ORDER BY channel_name", (server_id,))
        else:
            cursor.execute("SELECT channel_id, channel_name, server_id, is_active, added_at FROM discord_channels ORDER BY server_id, channel_name")
        rows = cursor.fetchall()
        cursor.close()
        return rows
    else:
        conn = get_connection()
        c = conn.cursor()
        if server_id:
            c.execute("SELECT channel_id, channel_name, server_id, is_active, added_at FROM discord_channels WHERE server_id = ? ORDER BY channel_name", (server_id,))
        else:
            c.execute("SELECT channel_id, channel_name, server_id, is_active, added_at FROM discord_channels ORDER BY server_id, channel_name")
        rows = [{"channel_id": r[0], "channel_name": r[1], "server_id": r[2], "is_active": bool(r[3]), "added_at": r[4]} for r in c.fetchall()]
        conn.close()
        return rows

def toggle_channel_status(channel_id: int, is_active: bool):
    db_type = get_db_type()
    
    try:
        if db_type == "mysql":
            conn = get_connection()
            cursor = conn.cursor()
            cursor.execute("UPDATE discord_channels SET is_active = %s WHERE channel_id = %s", 
                          (1 if is_active else 0, channel_id))
            conn.commit()
            cursor.close()
        else:
            conn = get_connection()
            c = conn.cursor()
            c.execute("UPDATE discord_channels SET is_active = ? WHERE channel_id = ?", 
                      (1 if is_active else 0, channel_id))
            conn.commit()
            conn.close()
        
        # Limpiar el cache para forzar re-lectura
        clear_channel_cache(channel_id)
        print(f"[DB] Canal {channel_id} actualizado a {is_active}, cache limpiado")
        
    except Exception as e:
        print(f"[DB] Error actualizando canal {channel_id}: {e}")
        raise

# Cache simple para estados de canales (evita consultas excesivas)
_channel_status_cache = {}
_cache_timeout = 5  # segundos
_last_cache_update = {}

def is_channel_enabled(channel_id: int) -> bool:
    global _channel_status_cache, _last_cache_update
    
    db_type = get_db_type()
    current_time = time.time()
    
    # Verificar si tenemos un cache válido
    if (channel_id in _channel_status_cache and 
        channel_id in _last_cache_update and 
        current_time - _last_cache_update[channel_id] < _cache_timeout):
        result = _channel_status_cache[channel_id]
        print(f"[DB Cache] Canal {channel_id} estado (cache): {result}")
        return result
    
    try:
        if db_type == "mysql":
            conn = get_connection()
            cursor = conn.cursor()
            cursor.execute("SELECT is_active FROM discord_channels WHERE channel_id = %s", (channel_id,))
            row = cursor.fetchone()
            cursor.close()
            print(f"[DB] MySQL Query: SELECT is_active FROM discord_channels WHERE channel_id = {channel_id}")
            print(f"[DB] MySQL Row: {row}")
            result = bool(row[0]) if row else False
        else:
            conn = get_connection()
            c = conn.cursor()
            c.execute("SELECT is_active FROM discord_channels WHERE channel_id = ?", (channel_id,))
            row = c.fetchone()
            conn.close()
            print(f"[DB] SQLite Query: SELECT is_active FROM discord_channels WHERE channel_id = {channel_id}")
            print(f"[DB] SQLite Row: {row}")
            result = bool(row[0]) if row else False
        
        # Actualizar cache
        _channel_status_cache[channel_id] = result
        _last_cache_update[channel_id] = current_time
        
        print(f"[DB] Canal {channel_id} estado (DB): {result} - Timestamp: {time.strftime('%H:%M:%S')}")
        return result
    except Exception as e:
        print(f"[DB] Error verificando canal {channel_id}: {e}")
        # En caso de error, devolver False por seguridad
        return False

def clear_channel_cache(channel_id: int = None):
    """Limpia el cache de un canal específico o de todos"""
    global _channel_status_cache, _last_cache_update
    if channel_id:
        _channel_status_cache.pop(channel_id, None)
        _last_cache_update.pop(channel_id, None)
        print(f"[DB] Cache limpiado para canal {channel_id}")
        # Forzar expiración inmediata poniendo un timestamp antiguo
        _last_cache_update[channel_id] = 0
    else:
        _channel_status_cache.clear()
        _last_cache_update.clear()
        print(f"[DB] Todo el cache de canales limpiado")

def delete_server_channels(server_id: int):
    """Elimina todos los canales de un servidor específico"""
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("DELETE FROM discord_channels WHERE server_id = %s", (server_id,))
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("DELETE FROM discord_channels WHERE server_id = ?", (server_id,))
        conn.commit()
        conn.close()

def delete_discord_server(server_id: int):
    """Elimina un servidor y todos sus canales"""
    db_type = get_db_type()
    
    if db_type == "mysql":
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute("DELETE FROM discord_servers WHERE server_id = %s", (server_id,))
        conn.commit()
        cursor.close()
    else:
        conn = get_connection()
        c = conn.cursor()
        c.execute("DELETE FROM discord_servers WHERE server_id = ?", (server_id,))
        conn.commit()
        conn.close()
