#!/usr/bin/env python3
"""
app.py - Backend principal de Auris con Flask y MySQL
Sistema de autenticación con encriptación de contraseñas
"""

import os
import sys
import json
import mysql.connector
from datetime import datetime, timedelta
from flask import Flask, request, jsonify, render_template, send_from_directory, redirect, make_response
from flask_cors import CORS
import bcrypt
import jwt
import docx2txt
import tempfile
from PyPDF2 import PdfReader
from werkzeug.utils import secure_filename
import base64
import requests
import shutil
import uuid
import asyncio

# Configuración de rutas
# Como app.py está en la raíz, el proyecto es __file__'s directorio
project_root = os.path.dirname(__file__)  # Directorio actual (raíz)
template_dir = os.path.join(project_root, 'frontend', 'templates')
static_dir = os.path.join(project_root, 'frontend', 'static')
TEMP_DIR = os.path.join(project_root, 'temp')


# Crear la aplicación Flask
app = Flask(__name__,
            template_folder=template_dir,
            static_folder=static_dir)
CORS(app, supports_credentials=True)

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

# Registrar blueprints
from backend.routes.tts_routes import tts_bp
app.register_blueprint(tts_bp)

from backend.routes.edge_tts_routes import edge_tts_bp
app.register_blueprint(edge_tts_bp, url_prefix='/api')


# Configurar clave secreta para sesiones
app.secret_key = os.environ.get('SECRET_KEY', 'auris-secret-key-2025')

# ===== CONFIGURACIÓN DE BASE DE DATOS MYSQL =====
DB_CONFIG = {
    'host': os.environ.get('DB_HOST', 'localhost'),
    'user': os.environ.get('DB_USER', 'myadmon'),
    'password': os.environ.get('DB_PASSWORD', 'Quick25$$.'),
    'database': os.environ.get('DB_NAME', 'Auris'),
    'port': int(os.environ.get('DB_PORT', '3306')),
    'charset': 'utf8mb4',
    'autocommit': True
}

# Configuración de JWT
JWT_SECRET_KEY = os.environ.get('JWT_SECRET_KEY', 'auris-jwt-secret-2025')
JWT_ACCESS_TOKEN_EXPIRES = int(os.environ.get('JWT_ACCESS_TOKEN_EXPIRES', '86400'))

def get_db_connection():
    """Función para obtener conexión a MySQL"""
    try:
        connection = mysql.connector.connect(**DB_CONFIG)
        return connection
    except mysql.connector.Error as e:
        return None

def init_database():
    """Inicializar base de datos y crear tablas si no existen"""
    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            return False
        cursor = connection.cursor()
        connection.commit()
        return True
    except mysql.connector.Error as e:
        return False
    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()

# ===== RUTAS DE PRUEBA =====
@app.route('/api/test-db')
def test_db():
    """Probar conexión a la base de datos"""
    connection = get_db_connection()
    if connection:
        try:
            cursor = connection.cursor()
            cursor.execute("SELECT 1")
            result = cursor.fetchone()
            cursor.close()
            connection.close()
            return jsonify({
                'status': 'success',
                'message': 'Conexión a MySQL exitosa',
                'database': DB_CONFIG['database'],
                'test_query': 'SELECT 1',
                'result': result[0] if result else None
            }), 200
        except Exception as e:
            if connection:
                connection.close()
            return jsonify({
                'status': 'error',
                'message': f'Error ejecutando query de prueba: {str(e)}'
            }), 500
    else:
        return jsonify({
            'status': 'error',
            'message': 'Error de conexión a MySQL'
        }), 500

# ===== RUTAS DE AUTENTICACIÓN =====
@app.route('/api/register', methods=['POST'])
def register():
    """Registro de nuevos usuarios"""
    try:
        print("📝 Procesando registro de usuario...")
        data = request.json
        
        if not all(k in data for k in ('nombre_usuario', 'correo_electronico', 'contraseña')):
            return jsonify({'error': 'Faltan datos requeridos'}), 400
        
        nombre_usuario = data['nombre_usuario'].strip()
        correo_electronico = data['correo_electronico'].strip().lower()
        contraseña = data['contraseña']
        
        if len(nombre_usuario) < 3:
            return jsonify({'error': 'El nombre de usuario debe tener al menos 3 caracteres'}), 400
        if len(contraseña) < 6:
            return jsonify({'error': 'La contraseña debe tener al menos 6 caracteres'}), 400
        if '@' not in correo_electronico:
            return jsonify({'error': 'Correo electrónico inválido'}), 400
        
        connection = None
        cursor = None
        try:
            connection = get_db_connection()
            if not connection:
                print("❌ Error de conexión en registro")
                return jsonify({'error': 'Error de conexión a la base de datos'}), 500
                
            cursor = connection.cursor()
            cursor.execute("SELECT id FROM Usuarios WHERE correo_electronico = %s OR nombre_usuario = %s", 
                           (correo_electronico, nombre_usuario))
            if cursor.fetchone():
                print("❌ Usuario ya existe")
                return jsonify({'error': 'El usuario o correo ya existe'}), 409
            
            hashed_password = bcrypt.hashpw(contraseña.encode('utf-8'), bcrypt.gensalt())
            cursor.execute("""
                INSERT INTO Usuarios (nombre_usuario, correo_electronico, contraseña) 
                VALUES (%s, %s, %s)
            """, (nombre_usuario, correo_electronico, hashed_password.decode('utf-8')))
            
            user_id = cursor.lastrowid
            print(f"✅ Usuario creado con ID: {user_id}")
            
            default_configs = [
                ('tipo_voz', 'mujer'),
                ('velocidad_lectura', '1.0'),
                ('tamaño_fuente', 'medium'),
                ('contraste_alto', 'false'),
                ('retroalimentacion_audio', 'true')
            ]
            for config_name, config_value in default_configs:
                cursor.execute("""
                    INSERT INTO Configuraciones_Usuario (usuario_id, nombre_configuracion, valor_configuracion) 
                    VALUES (%s, %s, %s)
                """, (user_id, config_name, config_value))
            
            connection.commit()
            print("✅ Registro completado exitosamente")
            
            return jsonify({
                'status': 'success',
                'message': 'Usuario registrado exitosamente',
                'user_id': user_id
            }), 201
            
        except mysql.connector.Error as e:
            return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
        except Exception as e:
            return jsonify({'error': f'Error interno: {str(e)}'}), 500
        finally:
            if cursor:
                cursor.close()
            if connection:
                connection.close()
    
    except Exception as e:
        return jsonify({'error': f'Error crítico: {str(e)}'}), 500

@app.route('/api/login', methods=['POST'])
def login():
    """Autenticación de usuarios"""
    try:
        data = request.json
        
        if not all(k in data for k in ('correo_electronico', 'contraseña')):
            return jsonify({'error': 'Faltan datos requeridos'}), 400
        
        correo_electronico = data['correo_electronico'].strip().lower()
        contraseña = data['contraseña']
        
        connection = None
        cursor = None
        try:
            connection = get_db_connection()
            if not connection:
                return jsonify({'error': 'Error de conexión a la base de datos'}), 500
                
            cursor = connection.cursor(dictionary=True)
            cursor.execute("SELECT * FROM Usuarios WHERE correo_electronico = %s", (correo_electronico,))
            usuario = cursor.fetchone()
            
            if not usuario:
                print("❌ Usuario no encontrado")
                return jsonify({'error': 'Credenciales inválidas'}), 401
            
            if not bcrypt.checkpw(contraseña.encode('utf-8'), usuario['contraseña'].encode('utf-8')):
                print("❌ Contraseña incorrecta")
                return jsonify({'error': 'Credenciales inválidas'}), 401
            
            payload = {
                'user_id': usuario['id'],
                'exp': datetime.utcnow() + timedelta(seconds=JWT_ACCESS_TOKEN_EXPIRES)
            }
            token = jwt.encode(payload, JWT_SECRET_KEY, algorithm='HS256')
            
            cursor.execute("SELECT nombre_configuracion, valor_configuracion FROM Configuraciones_Usuario WHERE usuario_id = %s", (usuario['id'],))
            configs = cursor.fetchall()
            
            configuraciones = {}
            for config in configs:
                key = config['nombre_configuracion']
                value = config['valor_configuracion']
                if key in ['contraste_alto', 'retroalimentacion_audio']:
                    configuraciones[key] = value.lower() == 'true'
                elif key == 'velocidad_lectura':
                    configuraciones[key] = float(value)
                else:
                    configuraciones[key] = value
            
            response = make_response(jsonify({
                'status': 'success',
                'message': 'Login exitoso',
                'token': token,
                'usuario': {
                    'id': usuario['id'],
                    'nombre_usuario': usuario['nombre_usuario'],
                    'correo_electronico': usuario['correo_electronico'],
                    'foto_perfil': usuario['foto_perfil']
                },
                'configuraciones': configuraciones
            }))
            response.set_cookie('auth_token', token,
                                httponly=False,
                                secure=False,
                                samesite='Lax',
                                max_age=86400,
                                path='/')
            return response
            
        except mysql.connector.Error as e:
            return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
        except Exception as e:
            return jsonify({'error': f'Error interno: {str(e)}'}), 500
        finally:
            if cursor:
                cursor.close()
            if connection:
                connection.close()
    
    except Exception as e:
        return jsonify({'error': f'Error crítico: {str(e)}'}), 500

# ===== MIDDLEWARE DE AUTENTICACIÓN =====
def verify_token(token):
    try:
        payload = jwt.decode(token, JWT_SECRET_KEY, algorithms=['HS256'])
        return payload['user_id']
    except jwt.ExpiredSignatureError:
        print("❌ Token expirado")
        return None
    except jwt.InvalidTokenError:
        print("❌ Token inválido")
        return None

def auth_required(f):
    def decorated_function(*args, **kwargs):
        token = None
        
        auth_header = request.headers.get('Authorization')
        if auth_header and auth_header.startswith('Bearer '):
            token = auth_header[7:]
            print(f"🔍 Token en Authorization: {token[:20]}...")
        elif 'auth_token' in request.cookies:
            token = request.cookies.get('auth_token')
            print(f"🔍 Token en cookie: {token[:20] if token else 'None'}...")
        elif 'token' in request.args:
            token = request.args.get('token')
            print(f"🔍 Token en query: {token[:20] if token else 'None'}...")
        
        if not token:
            print("❌ No se encontró token")
            if request.endpoint in ['inicio', 'modo_visual', 'modo_auditivo', 'biblioteca', 'configuracion']:
                return redirect('/')
            return jsonify({'error': 'Token requerido'}), 401
        
        user_id = verify_token(token)
        if not user_id:
            print("❌ Token inválido o expirado")
            if request.endpoint in ['inicio', 'modo_visual', 'modo_auditivo', 'biblioteca', 'configuracion']:
                return redirect('/')
            return jsonify({'error': 'Token inválido'}), 401
        
        request.user_id = user_id
        return f(*args, **kwargs)
    
    decorated_function.__name__ = f.__name__
    return decorated_function

# ===== RUTAS DE Documentos (CORREGIDAS) =====

@app.route('/api/documents', methods=['POST'])
@auth_required
def save_document():
    """Guardar documento del usuario"""
    print("🔍 Iniciando save_document...")
    
    try:
        data = request.json
        print(f"📝 Datos recibidos: {data}")
        
        if not data:
            return jsonify({'error': 'No se recibieron datos JSON'}), 400
            
        if not all(k in data for k in ('titulo', 'contenido')):
            return jsonify({'error': 'Faltan datos requeridos: titulo y contenido'}), 400
        
        titulo = data['titulo'].strip()
        contenido = data['contenido'].strip()
        
        if len(titulo) < 1:
            return jsonify({'error': 'El título no puede estar vacío'}), 400
        
        if len(titulo) > 50:
            return jsonify({'error': 'El título no puede exceder 50 caracteres'}), 400
        
        print(f"✅ Validación inicial pasada - Título: '{titulo}', Contenido: {len(contenido)} caracteres")
        
        # Variables para el audio
        nombre_archivo_audio = None
        ruta_archivo_audio = None
        ruta_relativa_audio = None
        tipo_mime = 'audio/mpeg'
        
        # Obtener configuración del usuario para la voz
        connection = None
        cursor_config = None
        
        try:
            connection = get_db_connection()
            if not connection:
                return jsonify({'error': 'Error de conexión a la base de datos'}), 500
                
            print("✅ Conexión a BD establecida")
            
            cursor_config = connection.cursor(dictionary=True)
            cursor_config.execute("SELECT nombre_configuracion, valor_configuracion FROM Configuraciones_Usuario WHERE usuario_id = %s", (request.user_id,))
            configs = cursor_config.fetchall()
            cursor_config.close()
            cursor_config = None
            
            print(f"✅ Configuraciones obtenidas: {len(configs)} items")
            
            # Convertir configuraciones a diccionario
            configuraciones = {}
            for config in configs:
                key = config['nombre_configuracion']
                value = config['valor_configuracion']
                if key in ['contraste_alto', 'retroalimentacion_audio']:
                    configuraciones[key] = value.lower() == 'true'
                elif key == 'velocidad_lectura':
                    configuraciones[key] = float(value)
                else:
                    configuraciones[key] = value
            
            voice_type = configuraciones.get('tipo_voz', 'mujer')
            speed = configuraciones.get('velocidad_lectura', 1.0)
            
            print(f"✅ Configuración TTS - Voz: {voice_type}, Velocidad: {speed}")
            
            # Llamar al endpoint de síntesis de voz
            tts_response = requests.post('http://localhost:5000/api/synthesize-speech', 
                                       json={
                                           'text': contenido,
                                           'voice_type': voice_type,
                                           'speed': speed
                                       }, timeout=30)
            
            print(f"📡 Respuesta TTS - Status: {tts_response.status_code}")
            
            if tts_response.status_code == 200:
                tts_data = tts_response.json()
                print(f"📡 Datos TTS: {tts_data}")
                
                if tts_data.get('success'):
                    # Crear nombre de archivo personalizado basado en el título
                    titulo_seguro = secure_filename(titulo)
                    if not titulo_seguro:
                        titulo_seguro = f"documento_{uuid.uuid4().hex[:8]}"
                    
                    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
                    nombre_archivo_audio = f"{titulo_seguro}_{timestamp}.mp3"
                    
                    # Crear directorio de destino si no existe
                    audio_dir = os.path.join(project_root, 'frontend', 'static', 'assets', 'audio')
                    os.makedirs(audio_dir, exist_ok=True)
                    
                    # Ruta absoluta del archivo
                    ruta_archivo_audio = os.path.join(audio_dir, nombre_archivo_audio)
                    
                    # Ruta relativa para guardar en BD (desde la raíz del proyecto web)
                    ruta_relativa_audio = f"/static/assets/audio/{nombre_archivo_audio}"
                    
                    
                    audio_url = tts_data['audio_url']
                    if audio_url.startswith('/static/'):
                        # Es una URL local, leer el archivo
                        audio_file_path = os.path.join(project_root, 'frontend', audio_url.lstrip('/'))
                        
                        if os.path.exists(audio_file_path):
                            # Copiar archivo temporal al destino final con nombre personalizado
                            shutil.copy2(audio_file_path, ruta_archivo_audio)
                            
                            
                            # Eliminar archivo temporal
                            try:
                                os.remove(audio_file_path)
                            except Exception as e:
                                print(f"⚠️ Error eliminando temporal: {e}")
                        else:
                            print(f"❌ Archivo temporal no encontrado: {audio_file_path}")
                            ruta_relativa_audio = None
                    else:
                        # Es una URL externa, descargar
                        print(f"🌐 Descargando audio desde URL externa: {audio_url}")
                        audio_response = requests.get(audio_url, timeout=30)
                        if audio_response.status_code == 200:
                            # Guardar archivo con nombre personalizado
                            with open(ruta_archivo_audio, 'wb') as f:
                                f.write(audio_response.content)
                            
                        else:
                            print(f"❌ Error descargando audio: {audio_response.status_code}")
                            ruta_relativa_audio = None
                else:
                    print(f"❌ Error en síntesis TTS: {tts_data.get('error')}")
            else:
                print(f"❌ Error llamando a TTS: {tts_response.status_code} - {tts_response.text}")
                
        except requests.exceptions.RequestException as e:
            print(f"❌ Error de red con TTS: {e}")
        except Exception as e:
            print(f"❌ Error generando audio: {e}")
            import traceback
            traceback.print_exc()
        
        # Insertar en base de datos
        cursor = None
        try:
            if not connection:
                connection = get_db_connection()
            if not connection:
                return jsonify({'error': 'Error de conexión a la base de datos'}), 500
                
            cursor = connection.cursor()
            
            # Mostrar estructura de la tabla para debugging
            cursor.execute("DESCRIBE Documentos")
            columns = cursor.fetchall()
            print(f"📊 Estructura tabla Documentos:")
            for col in columns:
                print(f"   - {col}")
            
            # Insertar documento (ajustado a tu estructura de tabla)
            print(f"💾 Insertando documento...")
            print(f"   - usuario_id: {request.user_id}")
            print(f"   - titulo: '{titulo}'")
            print(f"   - contenido: {len(contenido)} chars")
            print(f"   - nombre_archivo: '{nombre_archivo_audio}'")
            print(f"   - tipo_mime: '{tipo_mime}'")
            print(f"   - archivo_audio: '{ruta_relativa_audio}'")
            
            # Obtener tamaño del archivo si existe
            tamaño_archivo = None
            if ruta_archivo_audio and os.path.exists(ruta_archivo_audio):
                tamaño_archivo = os.path.getsize(ruta_archivo_audio)
                print(f"   - tamaño_archivo: {tamaño_archivo} bytes")
            
            cursor.execute("""
                                INSERT INTO Documentos 
                                    (usuario_id, titulo, contenido, nombre_archivo, tipo_mime, archivo_audio) 
                                            VALUES (%s, %s, %s, %s, %s, %s)
                                        """, (request.user_id, titulo, contenido, nombre_archivo_audio, tipo_mime, ruta_relativa_audio))
            document_id = cursor.lastrowid
            connection.commit()
            
            print(f"✅ Documento insertado con ID: {document_id}")
            
            audio_status = "con audio" if ruta_relativa_audio else "sin audio"
            
            response_data = {
                'status': 'success',
                'message': f'Documento guardado exitosamente {audio_status}',
                'document_id': document_id,
                'has_audio': ruta_relativa_audio is not None,
                'audio_filename': nombre_archivo_audio if ruta_relativa_audio else None,
                'audio_path': ruta_relativa_audio if ruta_relativa_audio else None,
                'audio_url': ruta_relativa_audio if ruta_relativa_audio else None
            }
            
            print(f"📤 Enviando respuesta: {response_data}")
            return jsonify(response_data), 201
            
        except mysql.connector.Error as e:
            print(f"❌ Error de MySQL: {e}")
            print(f"❌ Error code: {e.errno}")
            print(f"❌ SQL State: {e.sqlstate}")
            return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
        finally:
            if cursor:
                cursor.close()
                print("🔒 Cursor cerrado")
            if cursor_config:
                cursor_config.close()
                print("🔒 Cursor config cerrado")
            if connection:
                connection.close()
                print("🔒 Conexión cerrada")
                
    except Exception as e:
        print(f"❌ Error general en save_document: {e}")
        import traceback
        traceback.print_exc()
        return jsonify({'error': f'Error interno del servidor: {str(e)}'}), 500
    
@app.route('/api/documents', methods=['GET'])
@auth_required
def get_user_documents():
    """Obtener Documentos del usuario"""
    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            return jsonify({'error': 'Error de conexión a la base de datos'}), 500
            
        cursor = connection.cursor(dictionary=True)
        
        # Obtener Documentos del usuario
        cursor.execute("""
            SELECT id, titulo, contenido, 
                   CASE WHEN archivo_audio IS NOT NULL THEN TRUE ELSE FALSE END as has_audio,
                   nombre_archivo, tipo_mime, creado_en, actualizado_en 
            FROM Documentos 
            WHERE usuario_id = %s 
            ORDER BY actualizado_en DESC
        """, (request.user_id,))
        
        documents = cursor.fetchall()
        
        # Convertir datetime a string para JSON
        for doc in documents:
            if doc['creado_en']:
                doc['creado_en'] = doc['creado_en'].isoformat()
            if doc['actualizado_en']:
                doc['actualizado_en'] = doc['actualizado_en'].isoformat()
        
        return jsonify({
            'status': 'success',
            'documents': documents
        }), 200
        
    except mysql.connector.Error as e:
        return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()

@app.route('/api/documents/<int:document_id>', methods=['GET'])
@auth_required
def get_document(document_id):
    """Obtener un documento específico"""
    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            return jsonify({'error': 'Error de conexión a la base de datos'}), 500
            
        cursor = connection.cursor(dictionary=True)
        
        # Obtener documento específico del usuario
        cursor.execute("""
            SELECT id, titulo, contenido, 
                   CASE WHEN archivo_audio IS NOT NULL THEN TRUE ELSE FALSE END as has_audio,
                   nombre_archivo, tipo_mime, creado_en, actualizado_en 
            FROM Documentos 
            WHERE id = %s AND usuario_id = %s
        """, (document_id, request.user_id))
        
        document = cursor.fetchone()
        
        if not document:
            return jsonify({'error': 'Documento no encontrado'}), 404
        
        # Convertir datetime a string para JSON
        if document['creado_en']:
            document['creado_en'] = document['creado_en'].isoformat()
        if document['actualizado_en']:
            document['actualizado_en'] = document['actualizado_en'].isoformat()
        
        return jsonify({
            'status': 'success',
            'document': document
        }), 200
        
    except mysql.connector.Error as e:
        return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()

@app.route('/api/documents/<int:document_id>/audio', methods=['GET'])
@auth_required
def get_document_audio(document_id):
    """Obtener el audio de un documento específico"""
    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            return jsonify({'error': 'Error de conexión a la base de datos'}), 500
            
        cursor = connection.cursor()
        
        # Primero intentar obtener el archivo desde la ruta guardada
        cursor.execute("""
            SELECT nombre_archivo, tipo_mime, archivo_audio
            FROM Documentos 
            WHERE id = %s AND usuario_id = %s AND (nombre_archivo IS NOT NULL OR archivo_audio IS NOT NULL)
        """, (document_id, request.user_id))
        
        result = cursor.fetchone()
        
        if not result:
            return jsonify({'error': 'Audio no encontrado'}), 404
        
        nombre_archivo, tipo_mime, archivo_audio = result
        
        # Intentar servir desde archivo guardado primero
        if nombre_archivo:
            audio_file_path = os.path.join(project_root, 'frontend', 'static', 'assets', 'audio', nombre_archivo)
            if os.path.exists(audio_file_path):
                return send_from_directory(
                    os.path.join(project_root, 'frontend', 'static', 'assets', 'audio'),
                    nombre_archivo,
                    mimetype=tipo_mime or 'audio/mpeg',
                    as_attachment=False
                )
        
        # Fallback al BLOB si no existe el archivo
        if archivo_audio:
            from flask import Response
            response = Response(
                archivo_audio,
                mimetype=tipo_mime or 'audio/mpeg',
                headers={
                    'Content-Disposition': f'inline; filename="{nombre_archivo or "audio.mp3"}"',
                    'Cache-Control': 'public, max-age=3600'
                }
            )
            return response
        
        return jsonify({'error': 'Audio no disponible'}), 404
        
    except mysql.connector.Error as e:
        return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()

@app.route('/api/documents/<int:document_id>', methods=['PUT'])
@auth_required
def update_document(document_id):
    """Actualizar documento del usuario"""
    data = request.json
    
    if not data:
        return jsonify({'error': 'No se proporcionaron datos'}), 400
    
    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            return jsonify({'error': 'Error de conexión a la base de datos'}), 500
            
        cursor = connection.cursor()
        
        # Verificar que el documento pertenece al usuario
        cursor.execute("SELECT id FROM Documentos WHERE id = %s AND usuario_id = %s", 
                        (document_id, request.user_id))
        if not cursor.fetchone():
            return jsonify({'error': 'Documento no encontrado'}), 404
        
        # Construir query de actualización dinámicamente
        update_fields = []
        values = []
        
        if 'titulo' in data:
            titulo = data['titulo'].strip()
            if len(titulo) < 1:
                return jsonify({'error': 'El título no puede estar vacío'}), 400
            if len(titulo) > 50:
                return jsonify({'error': 'El título no puede exceder 50 caracteres'}), 400
            update_fields.append("titulo = %s")
            values.append(titulo)
        
        if 'contenido' in data:
            update_fields.append("contenido = %s")
            values.append(data['contenido'])
        
        if 'archivo_audio' in data:
            update_fields.append("archivo_audio = %s")
            values.append(data['archivo_audio'])
        
        if not update_fields:
            return jsonify({'error': 'No hay campos para actualizar'}), 400
        
        values.append(document_id)
        values.append(request.user_id)
        
        query = f"UPDATE Documentos SET {', '.join(update_fields)} WHERE id = %s AND usuario_id = %s"
        cursor.execute(query, values)
        connection.commit()
        
        return jsonify({
            'status': 'success',
            'message': 'Documento actualizado exitosamente'
        }), 200
        
    except mysql.connector.Error as e:
        return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()

@app.route('/api/documents/<int:document_id>', methods=['DELETE'])
@auth_required
def delete_document(document_id):
    """Eliminar documento del usuario"""
    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            return jsonify({'error': 'Error de conexión a la base de datos'}), 500
            
        cursor = connection.cursor()
        
        # Verificar que el documento pertenece al usuario y eliminarlo
        cursor.execute("DELETE FROM Documentos WHERE id = %s AND usuario_id = %s", 
                      (document_id, request.user_id))
        
        if cursor.rowcount == 0:
            return jsonify({'error': 'Documento no encontrado'}), 404
        
        connection.commit()
        
        return jsonify({
            'status': 'success',
            'message': 'Documento eliminado exitosamente'
        }), 200
        
    except mysql.connector.Error as e:
        return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()


@app.route('/api/audio-transcriptions', methods=['POST'])
@auth_required
def save_audio_transcription():
    print("🔧 Iniciando guardado de transcripción de audio...")  # Log inicio

    titulo = request.form.get('titulo')
    texto_transcrito = request.form.get('texto_transcrito')
    audio_file = request.files.get('archivo_audio')

    print(f"📄 Datos recibidos:")
    print(f"   - Título: {titulo}")
    print(f"   - Texto: {texto_transcrito[:50]}...")
    print(f"   - Archivo de audio: {'Sí' if audio_file else 'No'}")

    # Validación básica
    if not titulo or not texto_transcrito:
        print("❌ Faltan datos requeridos")
        return jsonify({'error': 'Faltan datos requeridos: título o texto transcrito'}), 400

    titulo = titulo.strip()
    texto_transcrito = texto_transcrito.strip()

    if len(titulo) < 1:
        print("❌ Título vacío")
        return jsonify({'error': 'El título no puede estar vacío'}), 400

    if len(titulo) > 255:
        print("❌ Título demasiado largo")
        return jsonify({'error': 'El título no puede exceder 255 caracteres'}), 400

    # Guardar audio si existe
    audio_path = None
    if audio_file:
        try:
            # ✅ Usar ruta absoluta con project_root
            audio_filename = secure_filename(f"{titulo}.webm")
            audio_path = os.path.join(project_root, 'frontend', 'static', 'assets', 'audio', audio_filename)
            
            # ✅ Crear directorio si no existe
            audio_dir = os.path.dirname(audio_path)
            os.makedirs(audio_dir, exist_ok=True)
            
            print(f"💾 Guardando audio en: {audio_path}")
            
            # ✅ Intentar guardar
            audio_file.save(audio_path)
            print(f"✅ Audio guardado exitosamente")

        except Exception as e:
            print(f"❌ Error al guardar el archivo de audio: {type(e).__name__}: {e}")
            return jsonify({'error': f'No se pudo guardar el audio: {str(e)}'}), 500

    # Guardar en base de datos
    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            print("❌ Error de conexión a la base de datos")
            return jsonify({'error': 'Error de conexión a la base de datos'}), 500

        cursor = connection.cursor()
        print("🗄️ Insertando en base de datos...")
        
        cursor.execute("""
            INSERT INTO Audio_a_Texto (usuario_id, archivo_audio, texto_transcrito, nombre_transcripcion)
            VALUES (%s, %s, %s, %s)
        """, (request.user_id, audio_path, texto_transcrito, titulo))
        
        connection.commit()
        print("✅ Transcripción guardada en BD")

        return jsonify({'status': 'success', 'message': 'Transcripción guardada exitosamente'}), 201

    except mysql.connector.Error as e:
        print(f"❌ Error en base de datos: {e}")
        return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500

    except Exception as e:
        print(f"❌ Error inesperado: {e}")
        return jsonify({'error': f'Error interno: {str(e)}'}), 500

    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()
            
@app.route('/api/audio-transcriptions', methods=['GET'])
@auth_required
def get_user_audio_transcriptions():
    """Obtener transcripciones de audio del usuario"""
    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            return jsonify({'error': 'Error de conexión a la base de datos'}), 500

        cursor = connection.cursor(dictionary=True)

        # Obtener transcripciones del usuario
        cursor.execute("""
            SELECT id, nombre_transcripcion, creado_en, actualizado_en
            FROM Audio_a_Texto
            WHERE usuario_id = %s
            ORDER BY actualizado_en DESC
        """, (request.user_id,))

        transcriptions = cursor.fetchall()

        # Convertir datetime a string para JSON
        for trans in transcriptions:
            if trans['creado_en']:
                trans['creado_en'] = trans['creado_en'].isoformat()
            if trans['actualizado_en']:
                trans['actualizado_en'] = trans['actualizado_en'].isoformat()

        return jsonify({
            'status': 'success',
            'transcriptions': transcriptions
        }), 200

    except mysql.connector.Error as e:
        return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()

@app.route('/api/audio-transcriptions/<int:transcription_id>', methods=['GET'])
@auth_required
def get_audio_transcription(transcription_id):
    """Obtener una transcripción específica"""
    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            return jsonify({'error': 'Error de conexión a la base de datos'}), 500

        cursor = connection.cursor(dictionary=True)

        # Obtener transcripción específica del usuario
        cursor.execute("""
            SELECT id, nombre_transcripcion, texto_transcrito, creado_en, actualizado_en
            FROM Audio_a_Texto
            WHERE id = %s AND usuario_id = %s
        """, (transcription_id, request.user_id))

        transcription = cursor.fetchone()

        if not transcription:
            return jsonify({'error': 'Transcripción no encontrada'}), 404

        # Convertir datetime a string para JSON
        if transcription['creado_en']:
            transcription['creado_en'] = transcription['creado_en'].isoformat()
        if transcription['actualizado_en']:
            transcription['actualizado_en'] = transcription['actualizado_en'].isoformat()

        return jsonify({
            'status': 'success',
            'transcription': transcription
        }), 200

    except mysql.connector.Error as e:
        return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()

@app.route('/api/audio-transcriptions/<int:transcription_id>/audio', methods=['GET'])
@auth_required
def get_audio_transcription_audio(transcription_id):
    """Obtener el audio de una transcripción específica"""
    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            return jsonify({'error': 'Error de conexión a la base de datos'}), 500

        cursor = connection.cursor()

        # Obtener el audio de la transcripción
        cursor.execute("""
            SELECT archivo_audio
            FROM Audio_a_Texto
            WHERE id = %s AND usuario_id = %s
        """, (transcription_id, request.user_id))

        result = cursor.fetchone()

        if not result:
            return jsonify({'error': 'Audio no encontrado'}), 404

        archivo_audio = result[0]

        if archivo_audio:
            from flask import Response
            response = Response(
                archivo_audio,
                mimetype='audio/mpeg',
                headers={
                    'Content-Disposition': f'inline; filename="audio_{transcription_id}.mp3"',
                    'Cache-Control': 'public, max-age=3600'
                }
            )
            return response

        return jsonify({'error': 'Audio no disponible'}), 404

    except mysql.connector.Error as e:
        return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()

@app.route('/api/audio-transcriptions/<int:transcription_id>', methods=['PUT'])
@auth_required
def update_audio_transcription(transcription_id):
    """Actualizar transcripción de audio del usuario"""
    data = request.json
    
    if not data:
        return jsonify({'error': 'No se proporcionaron datos'}), 400
    
    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            return jsonify({'error': 'Error de conexión a la base de datos'}), 500
            
        cursor = connection.cursor()
        
        # Verificar que la transcripción pertenece al usuario
        cursor.execute("SELECT id FROM Audio_a_Texto WHERE id = %s AND usuario_id = %s", 
                        (transcription_id, request.user_id))
        if not cursor.fetchone():
            return jsonify({'error': 'Documento no encontrado'}), 404
        
        # Construir query de actualización dinámicamente
        update_fields = []
        values = []
        
        if 'nombre_transcripcion' in data:
            nombre_transcripcion = data['nombre_transcripcion'].strip()
            if len(nombre_transcripcion) < 1:
                return jsonify({'error': 'El nombre de la transcripción no puede estar vacío'}), 400
            if len(nombre_transcripcion) > 50:
                return jsonify({'error': 'El nombre de la transcripción no puede exceder 50 caracteres'}), 400
            update_fields.append("nombre_transcripcion = %s")
            values.append(nombre_transcripcion)
        
        if 'texto_transcrito' in data:
            update_fields.append("texto_transcrito = %s")
            values.append(data['texto_transcrito'])
        
        if 'archivo_audio' in data:
            update_fields.append("archivo_audio = %s")
            values.append(data['archivo_audio'])
        
        if not update_fields:
            return jsonify({'error': 'No hay campos para actualizar'}), 400

        values.append(transcription_id)
        values.append(request.user_id)

        query = f"UPDATE Audio_a_Texto SET {', '.join(update_fields)} WHERE id = %s AND usuario_id = %s"
        cursor.execute(query, values)
        connection.commit()
        
        return jsonify({
            'status': 'success',
            'message': 'Documento actualizado exitosamente'
        }), 200
        
    except mysql.connector.Error as e:
        return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()

@app.route('/api/audio-transcriptions/<int:transcription_id>', methods=['DELETE'])
@auth_required
def delete_audio_transcription(transcription_id):
    """Eliminar una transcripción del usuario"""
    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            return jsonify({'error': 'Error de conexión a la base de datos'}), 500

        cursor = connection.cursor()

        # Verificar que la transcripción pertenece al usuario y eliminarla
        cursor.execute("DELETE FROM Audio_a_Texto WHERE id = %s AND usuario_id = %s",
                      (transcription_id, request.user_id))

        if cursor.rowcount == 0:
            return jsonify({'error': 'Transcripción no encontrada'}), 404

        connection.commit()

        return jsonify({
            'status': 'success',
            'message': 'Transcripción eliminada exitosamente'
        }), 200

    except mysql.connector.Error as e:
        return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()

# ===== RUTAS DE CONFIGURACIÓN DE USUARIO =====

@app.route('/api/user/config', methods=['GET'])
@auth_required
def get_user_config():
    """Obtener configuración del usuario"""
    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            return jsonify({'error': 'Error de conexión a la base de datos'}), 500
            
        cursor = connection.cursor(dictionary=True)
        
        # Obtener datos del usuario
        cursor.execute("SELECT id, nombre_usuario, correo_electronico, foto_perfil FROM Usuarios WHERE id = %s", (request.user_id,))
        usuario = cursor.fetchone()
        
        # Obtener configuraciones
        cursor.execute("SELECT nombre_configuracion, valor_configuracion FROM Configuraciones_Usuario WHERE usuario_id = %s", (request.user_id,))
        configs = cursor.fetchall()
        
        # Convertir configuraciones a diccionario
        configuraciones = {}
        for config in configs:
            key = config['nombre_configuracion']
            value = config['valor_configuracion']
            
            # Convertir valores según el tipo
            if key in ['contraste_alto', 'retroalimentacion_audio']:
                configuraciones[key] = value.lower() == 'true'
            elif key == 'velocidad_lectura':
                configuraciones[key] = float(value)
            else:
                configuraciones[key] = value
        
        return jsonify({
            'status': 'success',
            'usuario': usuario,
            'configuraciones': configuraciones
        }), 200
        
    except mysql.connector.Error as e:
        return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()

@app.route('/api/user/config', methods=['PUT'])
@auth_required
def update_user_config():
    """Actualizar configuración del usuario"""
    data = request.json
    
    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            return jsonify({'error': 'Error de conexión a la base de datos'}), 500
            
        cursor = connection.cursor()
        
        # Actualizar cada configuración
        for key, value in data.items():
            # Convertir valor a string para almacenar
            if isinstance(value, bool):
                str_value = 'true' if value else 'false'
            else:
                str_value = str(value)
            
            # Verificar si la configuración existe
            cursor.execute("SELECT id FROM Configuraciones_Usuario WHERE usuario_id = %s AND nombre_configuracion = %s", 
                          (request.user_id, key))
            
            if cursor.fetchone():
                # Actualizar configuración existente
                cursor.execute("""
                    UPDATE Configuraciones_Usuario 
                    SET valor_configuracion = %s 
                    WHERE usuario_id = %s AND nombre_configuracion = %s
                """, (str_value, request.user_id, key))
            else:
                # Crear nueva configuración
                cursor.execute("""
                    INSERT INTO Configuraciones_Usuario (usuario_id, nombre_configuracion, valor_configuracion) 
                    VALUES (%s, %s, %s)
                """, (request.user_id, key, str_value))
        
        connection.commit()
        
        return jsonify({
            'status': 'success',
            'message': 'Configuración actualizada exitosamente'
        }), 200
        
    except mysql.connector.Error as e:
        return jsonify({'error': f'Error de base de datos: {str(e)}'}), 500
    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()

# ===== RUTAS DE NAVEGACIÓN =====

@app.route('/')
def index():
    """Página de login"""
    return render_template('login.html')

@app.route('/modo_visual')
def modo_visual():
    """Página del asistente en modo visual"""
    return render_template('Modo_Visual.html')

@app.route('/modo_auditivo')
def modo_auditivo():
    """Página del asistente en modo auditivo"""
    return render_template('Modo_Auditivo.html')

@app.route('/biblioteca')
def biblioteca():
    """Página de la biblioteca de recursos"""
    return render_template('library.html')

@app.route('/configuracion')
def configuracion():
    """Página de configuración"""
    return render_template('config.html')

@app.route('/inicio')
def inicio():
    """Página principal después del login"""
    return render_template('index.html')

# ===== RUTAS DE PROCESAMIENTO DE ARCHIVOS =====

@app.route('/leer-archivo', methods=['POST'])
def leer_archivo():
    """Leer contenido de archivos subidos"""
    if 'file' not in request.files:
        return jsonify({'error': 'No se ha seleccionado ningún archivo'}), 400

    archivo = request.files['file']
    if archivo.filename == '':
        return jsonify({'error': 'Archivo vacío'}), 400

    filename = archivo.filename.lower()

    temp_path = None
    try:
        if filename.endswith('.txt'):
            contenido = archivo.read().decode('utf-8')

        elif filename.endswith('.pdf'):
            temp_path = os.path.join(TEMP_DIR, 'temp.pdf')
            archivo.save(temp_path)
            from PyPDF2 import PdfReader
            reader = PdfReader(temp_path)
            contenido = ""
            for page in reader.pages:
                text = page.extract_text()
                if text:
                    contenido += text

        elif filename.endswith('.docx'):
            temp_path = os.path.join(TEMP_DIR, 'temp.docx')
            archivo.save(temp_path)
            import docx2txt
            contenido = docx2txt.process(temp_path)

        else:
            return jsonify({'error': 'Formato no soportado. Usa .txt, .pdf o .docx'}), 400

        # ✅ Eliminar archivo temporal después de usarlo
        if temp_path and os.path.exists(temp_path):
            os.remove(temp_path)

        return jsonify({
            'status': 'success',
            'nombre': archivo.filename,
            'texto': contenido.strip()
        }), 200

    except Exception as e:
        # ✅ Limpiar en caso de error
        if temp_path and os.path.exists(temp_path):
            try:
                os.remove(temp_path)
            except:
                pass
        print(f"❌ Error procesando archivo: {str(e)}")
        return jsonify({'error': f'Error al leer el archivo: {str(e)}'}), 500

# ===== RUTAS DE HEALTH CHECK =====

@app.route('/health')
def health_check():

    """Health check endpoint"""
    connection = get_db_connection()
    db_status = 'connected' if connection else 'disconnected'
    if connection:
        connection.close()
    
    return jsonify({
        'status': 'healthy',
        'timestamp': datetime.now().isoformat(),
        'database': db_status
    }), 200

@app.route('/api/library-items', methods=['GET'])
@auth_required
def get_library_items():
    # ✅ Validar que request.user_id exista
    if not hasattr(request, 'user_id') or not request.user_id:
        print("❌ Error: request.user_id no está definido o es 0")
        return jsonify({'error': 'Usuario no autenticado correctamente'}), 401

    connection = None
    cursor = None
    try:
        connection = get_db_connection()
        if not connection:
            return jsonify({'error': 'Error de conexión a la base de datos'}), 500

        cursor = connection.cursor(dictionary=True)

        # === OBTENER DOCUMENTOS ===
        try:
            cursor.execute("""
                SELECT 
                    id, 
                    titulo, 
                    contenido, 
                    creado_en, 
                    actualizado_en,
                    archivo_audio IS NOT NULL as has_audio,
                    nombre_archivo
                FROM Documentos
                WHERE usuario_id = %s
                ORDER BY actualizado_en DESC
            """, (request.user_id,))
            documentos = cursor.fetchall()
            print(f"📄 Documentos encontrados: {len(documentos)}")  # Log
        except Exception as e:
            print(f"❌ Error en consulta Documentos: {e}")
            documentos = []

        # === OBTENER TRANSCRIPCIONES ===
        try:
            cursor.execute("""
                SELECT 
                    id, 
                    nombre_transcripcion as titulo, 
                    texto_transcrito as contenido, 
                    creado_en, 
                    actualizado_en, 
                    archivo_audio
                FROM Audio_a_Texto
                WHERE usuario_id = %s
                ORDER BY actualizado_en DESC
            """, (request.user_id,))
            transcripciones = cursor.fetchall()
            print(f"🎧 Transcripciones encontradas: {len(transcripciones)}")  # Log
        except Exception as e:
            print(f"❌ Error en consulta Audio_a_Texto: {e}")
            transcripciones = []

        # === PROCESAR ITEMS ===
        items = []

        for doc in documentos:
            items.append({
                'id': doc['id'],
                'titulo': doc['titulo'],
                'contenido': doc['contenido'],
                'tipo': 'documento',
                'has_audio': bool(doc['has_audio']),
                'creado_en': doc['creado_en'].isoformat() if doc['creado_en'] else None,
                'actualizado_en': doc['actualizado_en'].isoformat() if doc['actualizado_en'] else None,
                'nombre_archivo': doc['nombre_archivo']
            })

        for trans in transcripciones:
            items.append({
                'id': trans['id'],
                'titulo': trans['titulo'] or "Sin título",
                'contenido': trans['contenido'],
                'tipo': 'transcripcion',
                'has_audio': bool(trans['archivo_audio']),
                'creado_en': trans['creado_en'].isoformat() if trans['creado_en'] else None,
                'actualizado_en': trans['actualizado_en'].isoformat() if trans['actualizado_en'] else None,
                'nombre_archivo': trans['archivo_audio']  # Puedes usar este como nombre
            })

        # Ordenar por actualizado_en (más reciente primero)
        items.sort(key=lambda x: x['actualizado_en'] or '', reverse=True)

        return jsonify({
            'status': 'success',
            'items': items
        }), 200

    except Exception as e:
        print(f"❌ Error general en /api/library-items: {str(e)}")
        import traceback
        traceback.print_exc()  # Muestra el stack completo
        return jsonify({'error': 'Error interno del servidor'}), 500

    finally:
        if cursor:
            cursor.close()
        if connection:
            connection.close()

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

@app.route('/enviar-soporte', methods=['POST'])
def enviar_soporte():
    data = request.get_json()

    # Datos del correo
    sender_email = "webmaster@asistenteauris.com.co"
    sender_password = "Auris25$$"
    recipient_email = "webmaster@asistenteauris.com.co"

    # Configuración del servidor SMTP de Mi.com.co
    smtp_server = "smtp.mi.com.co"
    smtp_port = 465  # Puerto SSL

    # Crear mensaje
    msg = MIMEMultipart()
    msg['From'] = sender_email
    msg['To'] = recipient_email
    msg['Subject'] = f"[Soporte Auris] {data['asunto']}"

    body = f"""
    Nuevo mensaje de soporte desde la app Auris:

    Nombre: {data['nombre']}
    Email: {data['email']}
    Asunto: {data['asunto']}

    Mensaje:
    {data['mensaje']}
    """

    msg.attach(MIMEText(body, 'plain'))

    try:
        # Usar SMTP_SSL para puerto 465
        server = smtplib.SMTP_SSL(smtp_server, smtp_port)
        server.login(sender_email, sender_password)
        text = msg.as_string()
        server.sendmail(sender_email, recipient_email, text)
        server.quit()
        return jsonify({"success": True}), 200
    except Exception as e:
        print("Error al enviar:", str(e))
        return jsonify({"success": False, "error": str(e)}), 500

# ===== INICIALIZACIÓN =====

if __name__ == '__main__':
    print("🚀 Iniciando aplicación Auris...")
    
    # Inicializar base de datos
    if init_database():
        print("✅ Base de datos inicializada correctamente")
    else:
        print("⚠️ Error al inicializar base de datos")
    
    port = int(os.environ.get("PORT", 5000))
    print(f"🌐 Servidor ejecutándose en puerto {port}")
    
    debug_mode = os.environ.get('FLASK_ENV') == 'development'
    app.run(host='0.0.0.0', port=port, debug=debug_mode)