
# Para subir archivo tipo foto al servidor
from werkzeug.utils import secure_filename
import uuid  # Modulo de python para crear un string

from conexion.conexionBD import connectionBD  # Conexión a BD

import datetime
import re
import os


from os import remove  # Modulo  para remover archivo
from os import path  # Modulo para obtener la ruta o directorio

import openpyxl  # Para generar el excel
# biblioteca o modulo send_file para forzar la descarga
from flask import send_file
import json  # Para manejar JSON de documentos múltiples


def sql_lista_profesoresBD(id=None):
    try:
        with connectionBD() as conexion_MySQLdb:
            with conexion_MySQLdb.cursor(dictionary=True) as cursor:
                if id:
                    querySQL = ("""
                        SELECT
                            e.idprof,
                            e.codmodular,
                            e.apaterno,
                            e.amaterno,
                            e.nombres,
                            e.dniprof,
                            i.nombreie,
                            i.nivel,
                            i.direccion
                        FROM profesor AS e
                        LEFT JOIN iiee AS i ON e.codmodular = i.codmodular
                        WHERE e.codmodular = %s
                        ORDER BY e.apaterno ASC
                        LIMIT 100
                        """)
                    cursor.execute(querySQL, (id,))
                else:
                    querySQL = ("""
                        SELECT
                            e.idprof,
                            e.codmodular,
                            e.apaterno,
                            e.amaterno,
                            e.nombres,
                            e.dniprof,
                            i.nombreie,
                            i.nivel,
                            i.direccion
                        FROM profesor AS e
                        LEFT JOIN iiee AS i ON e.codmodular = i.codmodular
                        ORDER BY e.apaterno ASC
                        LIMIT 100
                        """)
                    cursor.execute(querySQL,)
                empleadosBD = cursor.fetchall()
        return empleadosBD
    except Exception as e:
        print(
            f"Error en la función sql_lista_profesorBD: {e}")
        return None

# Detalles del Empleado
def sql_detalles_ieBD(idie):
    try:
        with connectionBD() as conexion_MySQLdb:
            with conexion_MySQLdb.cursor(dictionary=True) as cursor:



                querySQL = ("""
                    SELECT
                        e.horario,
                        e.horario_estudiante,
                        e.pci,
                        e.rd_comite,
                        e.ri,
                        e.pat,
                        e.pei,
                        i.codmodular,
                        i.nombreie,
                        i.nivel,
                        i.direccion
                    FROM tbl_docie AS e
                    JOIN iiee AS i ON e.codmodular = i.codmodular
                    WHERE e.codmodular = %s
                    LIMIT 1
                    """)

                cursor.execute(querySQL, (idie,))
                result = cursor.fetchone()
                
                if result:
                    # Agregar documentos OTROS por separado
                    result['otros_documentos'] = sql_get_otros_documentos(idie)
                    empleadosBD = [result]
                else:
                    empleadosBD = []
                
        print(f"DEBUG: sql_detalles_ieBD for idie {idie}: {empleadosBD}")
        return empleadosBD[0] if empleadosBD else None
    except Exception as e:
        print(
            f"Error en la función sql_detalles_ieBD: {e}")
        return None
    
def procesar_actualizacionie_form(data, codmodular):
    try:
        with connectionBD() as conexion_MySQLdb:
            with conexion_MySQLdb.cursor(dictionary=True) as cursor:
                


                horario = data.form.get('horario', None)
                horario_estudiante = data.form.get('horario_estudiante', None)
                pci = data.form.get('pci', None)
                rd_comite = data.form.get('rd_comite', None)
                pei = data.form.get('pei', None)
                ri = data.form.get('ri', None)
                pat = data.form.get('pat', None)

                querySQL = """
                        UPDATE tbl_docie
                        SET
                            horario = %s,
                            horario_estudiante = %s,
                            pci = %s,
                            rd_comite = %s,
                            pei = %s,
                            ri = %s,
                            pat = %s
                        WHERE codmodular = %s
                    """
                values = (horario, horario_estudiante, pci, rd_comite, pei, ri, pat, codmodular)

                cursor.execute(querySQL, values)
                conexion_MySQLdb.commit()

        return cursor.rowcount or []
    except Exception as e:
        print(f"Ocurrió un error en procesar_actualizacionie_form: {e}")
        return None

def buscarIEUnico(id):
    try:
        with connectionBD() as conexion_MySQLdb:
            with conexion_MySQLdb.cursor(dictionary=True) as mycursor:


                querySQL = ("""
                        SELECT
                            e.codmodular,
                            e.horario,
                            e.horario_estudiante,
                            e.pci,
                            e.rd_comite,
                            e.ri,
                            e.pat,
                            e.pei
                        FROM tbl_docie AS e
                        WHERE e.codmodular =%s LIMIT 1
                    """)
                mycursor.execute(querySQL, (id,))
                result = mycursor.fetchone()
                
                if result:
                    # Agregar documentos OTROS por separado
                    result['otros_documentos'] = sql_get_otros_documentos(id)
                    return result
                return []

    except Exception as e:
        print(f"Ocurrió un error en def buscarEmpleadoUnico: {e}")
        return []

# Lista de Empleados
def sql_lista_ieBD():
    try:
        with connectionBD() as conexion_MySQLdb:
            with conexion_MySQLdb.cursor(dictionary=True) as cursor:

                querySQL = ("""
                    SELECT
                        e.codmodular,
                        e.horario,
                        e.horario_estudiante,
                        e.pci,
                        e.rd_comite,
                        e.pat,
                        e.pei,
                        e.ri
                    FROM tbl_docie AS e
                    LIMIT 100
                    """)
                cursor.execute(querySQL,)
                empleadosBD = cursor.fetchall()
        return empleadosBD
    except Exception as e:
        print(
            f"Errro en la función sql_lista_ieBD: {e}")
        return None

def lista_tbl_docie(id):
    try:
        # Primero obtenemos los datos del registro
        with connectionBD() as conexion_MySQLdb:
            with conexion_MySQLdb.cursor(dictionary=True) as cursor:

                querySQL = ("""
                    SELECT
                        e.codmodular,
                        e.horario,
                        e.horario_estudiante,
                        e.pci,
                        e.rd_comite,
                        e.ri,
                        e.pat,
                        e.pei
                    FROM tbl_docie AS e
                    WHERE e.codmodular = %s
                    """)
                cursor.execute(querySQL, (id,))
                datos_ie = cursor.fetchall()


        return datos_ie[0] if datos_ie else None
    except Exception as e:
        print(f"Error en lista_tbl_docie: {e}")
        return None

# Funciones para manejar documentos OTROS múltiples


def sql_get_otros_documentos(codmodular):
    """Obtener lista de documentos OTROS para una IE específica"""
    try:
        with connectionBD() as conexion_MySQLdb:
            with conexion_MySQLdb.cursor(dictionary=True) as cursor:
                querySQL = "SELECT otros FROM tbl_docie WHERE codmodular = %s LIMIT 1"
                cursor.execute(querySQL, (codmodular,))
                result = cursor.fetchone()
                
                if result and result['otros'] is not None:
                    # Si es string, intentar parsear como JSON
                    if isinstance(result['otros'], str):
                        try:
                            # Limpiar string antes de parsear JSON
                            otros_str = result['otros'].strip()
                            if otros_str:
                                # Intentar parsear como JSON
                                otros_docs = json.loads(otros_str)
                                if isinstance(otros_docs, list):
                                    # Validar estructura de cada documento
                                    validated_docs = []
                                    for doc in otros_docs:
                                        if isinstance(doc, dict) and all(key in doc for key in ['id', 'filename', 'display_name']):
                                            validated_docs.append(doc)
                                        else:
                                            print(f"Documento con estructura inválida encontrado para codmodular {codmodular}: {doc}")
                                    return validated_docs
                                else:
                                    # Si no es una lista, devolver lista vacía
                                    print(f"Campo 'otros' no contiene una lista válida para codmodular {codmodular}")
                                    return []
                            else:
                                return []
                        except json.JSONDecodeError as json_error:
                            # Si no es JSON válido, intentar limpiar datos corruptos
                            print(f"JSON inválido para codmodular {codmodular}: {json_error}")
                            print(f"Datos corruptos: {result['otros'][:100]}...")
                            
                            # Intentar limpiar datos corruptos
                            if sql_clean_corrupted_otros_data(codmodular):
                                print(f"Datos corruptos limpiados para codmodular {codmodular}")
                                return []
                            else:
                                print(f"No se pudieron limpiar los datos corruptos para codmodular {codmodular}")
                                return []
                        except Exception as parse_error:
                            print(f"Error al parsear datos para codmodular {codmodular}: {parse_error}")
                            return []
                    # Si ya es una lista
                    elif isinstance(result['otros'], list):
                        return result['otros']
                    else:
                        print(f"Tipo de datos inesperado en campo 'otros' para codmodular {codmodular}: {type(result['otros'])}")
                        return []
                
                return []
    except Exception as e:
        print(f"Error en sql_get_otros_documentos para codmodular {codmodular}: {e}")
        return []


def sql_clean_corrupted_otros_data(codmodular):
    """Limpiar datos corruptos en el campo otros"""
    try:
        with connectionBD() as conexion_MySQLdb:
            with conexion_MySQLdb.cursor(dictionary=True) as cursor:
                # Establecer el campo otros como NULL para limpiar datos corruptos
                querySQL = "UPDATE tbl_docie SET otros = NULL WHERE codmodular = %s"
                cursor.execute(querySQL, (codmodular,))
                conexion_MySQLdb.commit()
                return cursor.rowcount > 0
    except Exception as e:
        print(f"Error al limpiar datos corruptos para codmodular {codmodular}: {e}")
        try:
            if 'conexion_MySQLdb' in locals():
                conexion_MySQLdb.rollback()
        except:
            pass
        return False





def sql_add_otros_documento(codmodular, filename, display_name):
    """
    Agregar nuevo documento a la lista de documentos OTROS con manejo robusto de errores
    Retorna: (bool, str) - (success, message)
    VERSIÓN MEJORADA - Corrección para documentos múltiples
    """
    print(f"🔍 DEBUG sql_add_otros_documento: INICIANDO para codmodular={codmodular}")
    print(f"📝 DEBUG sql_add_otros_documento: filename='{filename}', display_name='{display_name}'")
    
    try:
        # Validar parámetros de entrada
        if not codmodular or not filename or not display_name:
            error_msg = f"Parámetros faltantes - codmodular={codmodular}, filename={filename}, display_name={display_name}"
            print(f"ERROR sql_add_otros_documento: {error_msg}")
            return False, error_msg
        
        # Sanitizar entrada más rigurosamente
        filename = str(filename).strip()
        display_name = str(display_name).strip()
        codmodular = str(codmodular).strip()
        
        # Validaciones específicas
        if not filename or not display_name or not codmodular:
            error_msg = "Parámetros vacíos después de sanitización"
            print(f"ERROR sql_add_otros_documento: {error_msg}")
            return False, error_msg
        
        # Validar longitud de nombres
        if len(display_name) > 255:
            error_msg = f"Nombre del documento muy largo: {len(display_name)} caracteres"
            print(f"ERROR sql_add_otros_documento: {error_msg}")
            return False, error_msg
            
        if len(filename) > 255:
            error_msg = f"Nombre de archivo muy largo: {len(filename)} caracteres"
            print(f"ERROR sql_add_otros_documento: {error_msg}")
            return False, error_msg
            
        print(f"DEBUG sql_add_otros_documento: Parámetros validados correctamente")
            
        with connectionBD() as conexion_MySQLdb:
            with conexion_MySQLdb.cursor(dictionary=True) as cursor:
                # Obtener documentos actuales con manejo de errores mejorado
                print(f"DEBUG sql_add_otros_documento: Obteniendo documentos actuales...")
                try:
                    otros_docs = sql_get_otros_documentos(codmodular)
                    print(f"DEBUG sql_add_otros_documento: Documentos actuales obtenidos: {len(otros_docs)} documentos")
                    
                    # Verificar si el documento ya existe
                    for existing_doc in otros_docs:
                        if existing_doc.get('filename') == filename:
                            error_msg = f"Ya existe un documento con el nombre: {filename}"
                            print(f"WARNING sql_add_otros_documento: {error_msg}")
                            return False, error_msg
                    
                except Exception as get_docs_error:
                    error_msg = f"Error al obtener documentos actuales: {str(get_docs_error)}"
                    print(f"ERROR sql_add_otros_documento: {error_msg}")
                    return False, error_msg
                
                # Crear nuevo documento
                import uuid
                from datetime import datetime as dt
                new_doc = {
                    "id": str(uuid.uuid4()),
                    "filename": filename,
                    "display_name": display_name,
                    "upload_date": dt.now().strftime("%Y-%m-%d %H:%M:%S")
                }
                print(f"DEBUG sql_add_otros_documento: Nuevo documento creado: {new_doc}")
                
                # Agregar a la lista
                otros_docs.append(new_doc)
                print(f"DEBUG sql_add_otros_documento: Lista actualizada con {len(otros_docs)} documentos")
                
                # Convertir a JSON de manera más segura
                try:
                    # Usar encoding específico para evitar problemas con caracteres especiales
                    json_data = json.dumps(otros_docs, ensure_ascii=False, separators=(',', ':'), indent=None)
                    print(f"DEBUG sql_add_otros_documento: JSON generado, longitud: {len(json_data)} caracteres")
                    
                    # Verificar que el JSON es válido antes de continuar
                    json.loads(json_data)  # Validar JSON
                    print(f"DEBUG sql_add_otros_documento: JSON válido confirmado")
                    
                except (TypeError, ValueError, json.JSONDecodeError) as json_error:
                    error_msg = f"Error al convertir JSON: {str(json_error)}"
                    print(f"ERROR sql_add_otros_documento: {error_msg}")
                    print(f"DEBUG sql_add_otros_documento: Contenido problemático: {otros_docs}")
                    return False, error_msg
                
                # Verificar el tamaño del JSON
                if len(json_data) > 65535:  # Límite típico para campo TEXT en MySQL
                    error_msg = f"JSON demasiado grande: {len(json_data)} caracteres (máximo: 65535)"
                    print(f"ERROR sql_add_otros_documento: {error_msg}")
                    return False, error_msg
                
                # Actualizar en base de datos con manejo de errores mejorado
                try:
                    print(f"DEBUG sql_add_otros_documento: Ejecutando UPDATE para codmodular {codmodular}")
                    
                    # Primero intentar UPDATE
                    querySQL = "UPDATE tbl_docie SET otros = %s WHERE codmodular = %s"
                    cursor.execute(querySQL, (json_data, codmodular))
                    
                    print(f"DEBUG sql_add_otros_documento: UPDATE ejecutado, filas afectadas: {cursor.rowcount}")
                    
                    if cursor.rowcount == 0:
                        print(f"DEBUG sql_add_otros_documento: No se actualizó ningún registro, verificando si existe...")
                        
                        # Verificar si el registro existe
                        checkSQL = "SELECT codmodular FROM tbl_docie WHERE codmodular = %s LIMIT 1"
                        cursor.execute(checkSQL, (codmodular,))
                        existe = cursor.fetchone()
                        
                        if existe:
                            error_msg = f"El registro existe para {codmodular} pero no se actualizó"
                            print(f"ERROR sql_add_otros_documento: {error_msg}")
                            return False, error_msg
                        else:
                            # Intentar insertar si el registro no existe
                            print(f"DEBUG sql_add_otros_documento: Insertando nuevo registro...")
                            insertSQL = "INSERT INTO tbl_docie (codmodular, otros) VALUES (%s, %s)"
                            cursor.execute(insertSQL, (codmodular, json_data))
                            conexion_MySQLdb.commit()
                            print(f"SUCCESS sql_add_otros_documento: Registro creado para codmodular {codmodular}")
                            return True, "Documento agregado exitosamente"
                    else:
                        conexion_MySQLdb.commit()
                        success_msg = f"Documento '{display_name}' agregado exitosamente para codmodular {codmodular}"
                        print(f"SUCCESS sql_add_otros_documento: {success_msg}")
                        return True, success_msg
                        
                except Exception as db_error:
                    error_msg = f"Error de base de datos: {str(db_error)}"
                    print(f"ERROR sql_add_otros_documento: {error_msg}")
                    try:
                        conexion_MySQLdb.rollback()
                        print(f"DEBUG sql_add_otros_documento: Rollback ejecutado debido a error de BD")
                    except:
                        pass
                    return False, error_msg
                
    except Exception as e:
        error_msg = f"Error general: {str(e)}"
        print(f"ERROR sql_add_otros_documento: {error_msg}")
        print(f"DEBUG sql_add_otros_documento: Parámetros: codmodular={codmodular}, filename={filename}, display_name={display_name}")
        import traceback
        print(f"DEBUG sql_add_otros_documento: Traceback completo: {traceback.format_exc()}")
        
        try:
            # Rollback en caso de error
            if 'conexion_MySQLdb' in locals():
                conexion_MySQLdb.rollback()
                print(f"DEBUG sql_add_otros_documento: Rollback general ejecutado")
        except:
            pass
        return False, error_msg


def sql_check_otros_field_type(codmodular):
    """Función de diagnóstico para verificar el tipo y contenido del campo otros"""
    try:
        with connectionBD() as conexion_MySQLdb:
            with conexion_MySQLdb.cursor(dictionary=True) as cursor:
                # Verificar estructura de la tabla
                cursor.execute("DESCRIBE tbl_docie")
                columns = cursor.fetchall()
                otros_column = next((col for col in columns if col['Field'] == 'otros'), None)
                
                if otros_column:
                    print(f"DEBUG sql_check_otros_field_type: Campo 'otros' - Tipo: {otros_column['Type']}, Null: {otros_column['Null']}, Default: {otros_column['Default']}")
                else:
                    print(f"DEBUG sql_check_otros_field_type: Campo 'otros' no encontrado en la tabla")
                
                # Verificar contenido actual
                querySQL = "SELECT codmodular, otros FROM tbl_docie WHERE codmodular = %s LIMIT 1"
                cursor.execute(querySQL, (codmodular,))
                result = cursor.fetchone()
                
                if result:
                    print(f"DEBUG sql_check_otros_field_type: Contenido actual para {codmodular}: {result['otros']}")
                    print(f"DEBUG sql_check_otros_field_type: Tipo del contenido: {type(result['otros'])}")
                    if result['otros']:
                        print(f"DEBUG sql_check_otros_field_type: Longitud del contenido: {len(str(result['otros']))}")
                else:
                    print(f"DEBUG sql_check_otros_field_type: No hay registro para {codmodular}")
                
                return True
                
    except Exception as e:
        print(f"ERROR sql_check_otros_field_type: {e}")
        return False

def sql_delete_otros_documento(codmodular, doc_id):
    """Eliminar documento específico de la lista OTROS"""
    try:
        with connectionBD() as conexion_MySQLdb:
            with conexion_MySQLdb.cursor(dictionary=True) as cursor:
                # Obtener documentos actuales
                otros_docs = sql_get_otros_documentos(codmodular)
                
                # Buscar y eliminar el documento
                filename_to_delete = None
                otros_docs_updated = [doc for doc in otros_docs if doc.get('id') != doc_id]
                
                # Si se encontró el documento, obtener el nombre del archivo para eliminarlo
                for doc in otros_docs:
                    if doc.get('id') == doc_id:
                        filename_to_delete = doc.get('filename')
                        break
                
                # Actualizar en base de datos
                if otros_docs_updated:
                    querySQL = "UPDATE tbl_docie SET otros = %s WHERE codmodular = %s"
                    cursor.execute(querySQL, (json.dumps(otros_docs_updated, ensure_ascii=False), codmodular))
                else:
                    # Si no hay documentos, establecer NULL
                    querySQL = "UPDATE tbl_docie SET otros = NULL WHERE codmodular = %s"
                    cursor.execute(querySQL, (codmodular,))
                
                conexion_MySQLdb.commit()
                
                return filename_to_delete
    except Exception as e:
        print(f"Error en sql_delete_otros_documento: {e}")
        return None

def get_otros_document_path(codmodular, filename):
    """Obtener ruta completa del archivo OTROS"""
    base_path = '/var/www/my-app/static/tbl_docie/'
    return os.path.join(base_path, str(codmodular), filename)
