# --- x5_refactored.py ---
import json
from typing import List, Dict, Any, Optional
import sys
import os
import glob
from datetime import datetime

script_root = os.path.dirname(
    os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
)
sys.path.append(script_root)
from backend.script_utils import load_configuration

# Importar funciones comunes desde x3
from x3 import flatten_db_structure, format_address_for_display
from x4 import format_data_type_for_source

def find_working_directory():
    configs = load_configuration()
    working_directory = configs.get("working_directory")
    if not working_directory:
        print("No working directory specified in the configuration file.")
        sys.exit(1)
    return working_directory

def generate_members_table_md(
    db_info: Dict[str, Any], 
    is_udt_definition: bool = False, 
    include_current_value: bool = True
) -> List[str]:
    """
    Genera tabla markdown para todos los miembros usando las funciones de aplanamiento de x3.
    """
    lines = []
    
    # Definir columnas de la tabla
    if include_current_value:
        header = "| Nombre Miembro (Ruta) | Tipo de Dato | Offset (Byte.Bit) | Tamaño (Bytes) | Tamaño (Bits) | Valor Inicial (Decl.) | Valor Actual (Efectivo) | Comentario |"
        separator = "|---|---|---|---|---|---|---|---|"
    else:
        header = "| Nombre Miembro | Tipo de Dato | Offset (Byte.Bit) | Tamaño (Bytes) | Tamaño (Bits) | Valor Inicial | Comentario |"
        separator = "|---|---|---|---|---|---|---|"
    
    lines.append(header)
    lines.append(separator)
    
    # Usar la función de aplanamiento importada
    flat_vars = flatten_db_structure(db_info)
    
    # Generar filas para cada variable
    for var in flat_vars:
        # Usar la dirección formateada desde flatten_db_structure
        address = var.get("address_display", format_address_for_display(var["byte_offset"], var.get("bit_size", 0)))
        name_display = f"`{var['full_path']}`"
        data_type_display = f"`{format_data_type_for_source(var)}`"
        size_bytes_display = str(var.get('size_in_bytes', '0'))
        bit_size_display = str(var.get('bit_size', '0')) if var.get('bit_size', 0) > 0 else ""
        
        initial_value = str(var.get('initial_value', '')).replace("|", "\\|").replace("\n", " ")
        initial_value_display = f"`{initial_value}`" if initial_value else ""
        
        comment_display = str(var.get('comment', '')).replace("|", "\\|").replace("\n", " ")
        
        if include_current_value:
            current_value = str(var.get('current_value', '')).replace("|", "\\|").replace("\n", " ")
            current_value_display = f"`{current_value}`" if current_value else ""
            row = f"| {name_display} | {data_type_display} | {address} | {size_bytes_display} | {bit_size_display} | {initial_value_display} | {current_value_display} | {comment_display} |"
        else:
            row = f"| {name_display} | {data_type_display} | {address} | {size_bytes_display} | {bit_size_display} | {initial_value_display} | {comment_display} |"
        
        lines.append(row)
    
    return lines

def generate_begin_block_documentation(db_info: Dict[str, Any]) -> List[str]:
    """
    Genera documentación para el bloque BEGIN utilizando flatten_db_structure.
    """
    lines = []
    lines.append("#### Contenido del Bloque `BEGIN` (Valores Actuales Asignados):")
    lines.append("El bloque `BEGIN` define los valores actuales de las variables en el DB. Las siguientes asignaciones son ordenadas por offset:")
    lines.append("")
    
    # Usar la función de aplanamiento importada de x3
    flat_vars = flatten_db_structure(db_info)
    
    # Filtrar solo variables con valores actuales
    vars_with_values = [var for var in flat_vars if var.get("current_value") is not None]
    
    if vars_with_values:
        lines.append("```scl")
        for var in vars_with_values:
            value_str = str(var["current_value"])
            if value_str.lower() == "true": value_str = "TRUE"
            elif value_str.lower() == "false": value_str = "FALSE"
            
            lines.append(f"  {var['full_path']} := {value_str};")
        lines.append("```")
        lines.append("")
    else:
        lines.append("No se encontraron asignaciones de valores actuales.")
        lines.append("")
    
    return lines

def generate_json_documentation(data: Dict[str, Any], output_filename: str):
    """Genera la documentación Markdown completa para el archivo JSON parseado."""
    lines = []
    lines.append(f"# Documentación del Archivo de Datos S7 Parseado")
    current_date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    lines.append(f"_Generado el: {current_date}_")
    lines.append("")
    lines.append("Este documento describe la estructura y el contenido del archivo JSON generado por el parser de fuentes S7 (`x3.py`).")
    lines.append("")

    # --- Sección UDTs ---
    lines.append("## 1. Tipos de Datos de Usuario (UDTs)")
    lines.append("")
    if data.get("udts"):
        for udt in data["udts"]:
            lines.append(f'### 1.{data["udts"].index(udt) + 1}. UDT: `{udt["name"]}`')
            if udt.get("family"): lines.append(f"- **Familia**: {udt['family']}")
            if udt.get("version"): lines.append(f"- **Versión**: {udt['version']}")
            lines.append(f"- **Tamaño Total**: {udt['total_size_in_bytes']} bytes")
            lines.append("")
            lines.append("#### Miembros del UDT:")
            
            # Usar la función optimizada para generar tabla
            udt_member_lines = generate_members_table_md(udt, is_udt_definition=True, include_current_value=False)
            lines.extend(udt_member_lines)
            lines.append("")
    else:
        lines.append("No se encontraron UDTs en el archivo JSON.")
    lines.append("")

    # --- Sección DBs ---
    lines.append("## 2. Bloques de Datos (DBs)")
    lines.append("")
    if data.get("dbs"):
        for db in data["dbs"]:
            lines.append(f'### 2.{data["dbs"].index(db) + 1}. DB: `{db["name"]}`')
            if db.get("title"): lines.append(f"- **TITLE**: `{db['title']}`")
            if db.get("family"): lines.append(f"- **Familia**: {db['family']}")
            if db.get("version"): lines.append(f"- **Versión**: {db['version']}")
            lines.append(f"- **Tamaño Declaraciones**: {db['total_size_in_bytes']} bytes")
            lines.append("")
            
            lines.append("#### Miembros del DB (Sección de Declaración):")
            db_member_lines = generate_members_table_md(db, include_current_value=True)
            lines.extend(db_member_lines)
            lines.append("")

            # Generar sección BEGIN usando la función optimizada
            begin_lines = generate_begin_block_documentation(db)
            lines.extend(begin_lines)
            
    else:
        lines.append("No se encontraron DBs en el archivo JSON.")

    # Guardar el archivo Markdown
    try:
        with open(output_filename, 'w', encoding='utf-8') as f:
            for line in lines:
                f.write(line + "\n")
        print(f"Documentación Markdown completa generada: {output_filename}")
    except Exception as e:
        print(f"Error al escribir el archivo Markdown de documentación {output_filename}: {e}")

if __name__ == "__main__":
    working_dir = find_working_directory()
    print(f"Using working directory: {working_dir}")

    input_json_dir = os.path.join(working_dir, "json")
    documentation_dir = os.path.join(working_dir, "documentation")
    os.makedirs(documentation_dir, exist_ok=True)
    print(f"Los archivos Markdown de descripción se guardarán en: {documentation_dir}")

    json_files_to_process = glob.glob(os.path.join(input_json_dir, "*.json"))

    if not json_files_to_process:
        print(f"No se encontraron archivos .json en {input_json_dir}")
    else:
        print(f"Archivos JSON encontrados para procesar: {len(json_files_to_process)}")

        for json_input_filepath in json_files_to_process:
            json_filename_base = os.path.splitext(os.path.basename(json_input_filepath))[0]
            current_json_filename = os.path.basename(json_input_filepath)
            print(f"\n--- Procesando archivo JSON para descripción: {current_json_filename} ---")

            markdown_output_filename = os.path.join(documentation_dir, f"{json_filename_base}_description.md")
            
            try:
                with open(json_input_filepath, 'r', encoding='utf-8') as f:
                    data_from_json = json.load(f)
                print(f"Archivo JSON '{current_json_filename}' cargado correctamente.")
            except Exception as e:
                print(f"Error al leer el archivo JSON {json_input_filepath}: {e}")
                continue

            try:
                generate_json_documentation(data_from_json, markdown_output_filename)
            except Exception as e:
                print(f"Error al generar la documentación para {current_json_filename}: {e}")

        print("\n--- Proceso de generación de descripciones Markdown completado ---")