# utils/docx_converter.py
import os
import re
import mammoth
from pathlib import Path
from models.pagina_html import PaginaHTML

def procesar_docx(ruta_archivo, dir_adjuntos):
    """
    Procesa un archivo DOCX y lo convierte directamente a Markdown,
    extrayendo las imágenes al directorio de adjuntos.
    """
    # Asegurar que el directorio de adjuntos existe
    os.makedirs(dir_adjuntos, exist_ok=True)
    
    # Lista para almacenar imágenes procesadas
    imagenes_procesadas = []
    
    def manejar_imagen(image):
        """Procesa cada imagen encontrada en el documento DOCX."""
        try:
            # Generar nombre de archivo para la imagen
            extension = image.content_type.split('/')[-1] if hasattr(image, 'content_type') else 'png'
            if extension == 'jpeg':
                extension = 'jpg'
            
            # Usar alt_text si está disponible o generar nombre basado en índice
            filename = (image.alt_text if hasattr(image, 'alt_text') and image.alt_text 
                        else f"image-{len(imagenes_procesadas)+1}.{extension}")
            
            # Asegurar que el nombre sea válido para el sistema de archivos
            filename = re.sub(r'[<>:"/\\|?*]', "_", filename)
            if not filename.endswith(f".{extension}"):
                filename = f"{filename}.{extension}"
            
            # Ruta completa para guardar la imagen
            image_path = os.path.join(dir_adjuntos, filename)
            
            # Verificar si el objeto imagen tiene el atributo 'content'
            if hasattr(image, 'content') and image.content:
                # Guardar la imagen
                with open(image_path, 'wb') as f:
                    f.write(image.content)
                
                # Agregar a la lista de imágenes procesadas
                if filename not in imagenes_procesadas:
                    imagenes_procesadas.append(filename)
                
                # Retornar el formato para Obsidian
                return {"src": filename}
            else:
                # Si no hay contenido, registrar el problema
                print(f"Advertencia: No se pudo extraer contenido de imagen '{filename}'")
                # Retornar un marcador de posición
                return {"src": "imagen_no_disponible.png"}
                
        except Exception as e:
            print(f"Error procesando imagen en DOCX: {str(e)}")
            # En caso de error, retornar un marcador de texto
            return {"alt": "Imagen no disponible"}
    
    try:
        # Configurar opciones de conversión personalizada para manejar casos problemáticos
        options = {
            "ignore_empty_paragraphs": True,
            "style_map": "p[style-name='Heading 1'] => h1:fresh"
        }
        
        # Abrir el archivo DOCX
        with open(ruta_archivo, "rb") as docx_file:
            # Convertir con manejo de errores mejorado
            result = mammoth.convert_to_markdown(
                docx_file,
                convert_image=mammoth.images.img_element(manejar_imagen),
                options=options
            )
            
            # Extraer el título (primera línea como encabezado)
            markdown_content = result.value
            lines = markdown_content.strip().split('\n')
            titulo = None
            
            # Buscar el primer encabezado para usar como título
            for line in lines:
                if line.startswith('#'):
                    # Eliminar los símbolos # y espacios
                    titulo = re.sub(r'^#+\s*', '', line).strip()
                    break
            
            # Si no hay encabezado, usar el nombre del archivo
            if not titulo:
                titulo = Path(ruta_archivo).stem
            
            # Mostrar advertencias de la conversión
            warnings = result.messages
            if warnings:
                print(f"Advertencias en la conversión:")
                for warning in warnings:
                    print(f"- {warning}")
            
            # Post-procesar para formato Obsidian
            markdown_content = post_procesar_markdown_obsidian(markdown_content, imagenes_procesadas)
            
            # Crear objeto PaginaHTML
            return PaginaHTML(
                ruta_archivo=ruta_archivo,
                titulo=titulo,
                contenido=markdown_content,
                imagenes=imagenes_procesadas
            )
    
    except Exception as e:
        print(f"Error procesando DOCX {ruta_archivo}: {str(e)}")
        return PaginaHTML(
            ruta_archivo=ruta_archivo,
            contenido=f"Error al procesar: {str(e)}"
        )

def post_procesar_markdown_obsidian(markdown, imagenes):
    """
    Realiza ajustes adicionales al markdown para formato Obsidian.
    """
    # 1. Convertir referencias de imágenes al formato Obsidian
    for imagen in imagenes:
        # Buscar referencias de imágenes en formato estándar
        # y convertirlas al formato Obsidian
        markdown = re.sub(
            r'!\[(.*?)\]\(' + re.escape(imagen) + r'\)',
            f'![[{imagen}]]',
            markdown
        )
    
    # 2. Agregar salto de línea adicional después de cada encabezado
    markdown = re.sub(r'(^|\n)(#+\s.*?)(\n(?!\n))', r'\1\2\n\3', markdown)
    
    # 3. Arreglar listas mal formadas (asegurar espacio después de * o -)
    markdown = re.sub(r'(^|\n)([*\-])([^\s])', r'\1\2 \3', markdown)
    
    # 4. Mejorar formato de tablas
    # Asegurar que hay línea en blanco antes y después de tablas
    markdown = re.sub(r'([^\n])\n(\|[^\n]+\|)', r'\1\n\n\2', markdown)
    markdown = re.sub(r'(\|[^\n]+\|)\n([^\n\|])', r'\1\n\n\2', markdown)
    
    # 5. Normalizar fin de líneas
    markdown = markdown.replace('\r\n', '\n')
    
    # 6. Eliminar líneas en blanco consecutivas excesivas
    markdown = re.sub(r'\n{3,}', '\n\n', markdown)
    
    return markdown