"""
convert Excel Tags to md : This script converts Excel files containing tags into Markdown tables.
Updated to work with a single Excel file and filter based on paths defined in a JSON config.
Also converts IO Excel file from electrical diagram to Markdown.
"""

# Standard library imports
import os
import sys
import json
import tkinter as tk
from tkinter import filedialog

# Third-party imports
try:
    import pandas as pd
except ImportError:
    print(
        "Error: La librería 'pandas' no está instalada. Por favor, instálala con 'pip install pandas openpyxl'."
    )
    sys.exit(1)

# Determine script_root and add to sys.path for custom module import
try:
    current_script_path = os.path.abspath(__file__)
    script_root = os.path.dirname(
        os.path.dirname(os.path.dirname(os.path.dirname(current_script_path)))
    )
    if script_root not in sys.path:
        sys.path.append(script_root)

    from backend.script_utils import load_configuration

except ImportError:
    print(
        "Error: No se pudo importar 'load_configuration' desde 'backend.script_utils'."
    )
    sys.exit(1)
except NameError:  # __file__ is not defined
    print(
        "Error: __file__ no está definido. Este script podría no estar ejecutándose en un entorno Python estándar."
    )
    sys.exit(1)


def load_path_config():
    """
    Carga la configuración de paths desde un archivo JSON
    Si no existe, crea uno con valores predeterminados en el working_directory
    """
    # Obtener la configuración global
    configs = load_configuration()
    working_directory = configs.get("working_directory")

    if not working_directory:
        print("Error: 'working_directory' no se encontró en la configuración.")
        return None

    if not os.path.isdir(working_directory):
        print(
            f"Error: El directorio de trabajo '{working_directory}' no existe o no es un directorio."
        )
        return None

    # Path para el archivo JSON de configuración
    json_config_path = os.path.join(working_directory, "io_paths_config.json")

    # Si el archivo existe, cargarlo
    if os.path.exists(json_config_path):
        try:
            with open(json_config_path, "r", encoding="utf-8") as f:
                config = json.load(f)
                print(f"Configuración de paths cargada desde: {json_config_path}")
                return config
        except Exception as e:
            print(f"Error al cargar el archivo de configuración JSON: {e}")
            return None

    # Si no existe, crear uno con valores predeterminados
    default_config = {
        "paths": [
            {
                "path": "Inputs",
                "type": "Input",
                "no_used_path": "IO Not in Hardware\\InputsMaster",
            },
            {
                "path": "Outputs",
                "type": "Output",
                "no_used_path": "IO Not in Hardware\\OutputsMaster",
            },
            {
                "path": "OutputsFesto",
                "type": "Output",
                "no_used_path": "IO Not in Hardware\\OutputsMaster",
            },
            {
                "path": "IO Not in Hardware\\InputsMaster",
                "type": "Input",
                "no_used_path": "IO Not in Hardware\\InputsMaster",
            },
            {
                "path": "IO Not in Hardware\\OutputsMaster",
                "type": "Output",
                "no_used_path": "IO Not in Hardware\\OutputsMaster",
            },
        ]
    }

    try:
        with open(json_config_path, "w", encoding="utf-8") as f:
            json.dump(default_config, f, indent=2)
        print(f"Archivo de configuración creado: {json_config_path}")
        return default_config
    except Exception as e:
        print(f"Error al crear el archivo de configuración JSON: {e}")
        return None


def convert_io_excel_to_markdown():
    """
    Convierte el archivo Excel de IO desde el esquema eléctrico a Markdown.
    Utiliza la configuración io_excel_file_from_ediagram para obtener la ruta del archivo.
    """
    try:
        configs = load_configuration()
        working_directory = configs.get("working_directory")
        level2_configs = configs.get("level2", {})
        level3_configs = configs.get("level3", {})
        io_excel_file = level3_configs.get("io_excel_file_from_ediagram")
        resultados_exp_directory = level2_configs.get("resultados_exp_directory", ".")

        if not working_directory or not os.path.isdir(working_directory):
            print(
                f"Error: El directorio de trabajo '{working_directory}' no es válido."
            )
            return False
    except Exception as e:
        print(f"Error al cargar la configuración: {e}")
        return False

    working_directory_abs = os.path.abspath(working_directory)
    print(f"Usando directorio de trabajo: {working_directory_abs}")

    # Construir la ruta del archivo Excel de IO
    if io_excel_file:
        excel_file_path = os.path.join(working_directory_abs, io_excel_file)
        if not os.path.exists(excel_file_path):
            print(f"Error: El archivo Excel de IO '{excel_file_path}' no existe.")
            return False
    else:
        print("Error: 'io_excel_file_from_ediagram' no está configurado en level3.")
        return False

    print(f"Procesando archivo Excel de IO: {excel_file_path}...")

    output_dir_abs = os.path.join(working_directory_abs, resultados_exp_directory)
    os.makedirs(output_dir_abs, exist_ok=True)
    output_md_filename = "Hardware_ED.md"
    output_md_filepath_abs = os.path.join(output_dir_abs, output_md_filename)

    try:
        # Leer el Excel de IO
        excel_data = pd.read_excel(excel_file_path, sheet_name=0)

        # Verificar que el archivo no esté vacío
        if excel_data.empty:
            print(f"Error: El archivo Excel '{excel_file_path}' está vacío.")
            return False

        # Obtener las columnas del Excel
        columns = list(excel_data.columns)
        print(f"Columnas encontradas en el Excel: {columns}")

        # Crear el contenido Markdown
        markdown_content = []
        markdown_content.append("# IO desde Esquema Eléctrico\n")

        # Crear la tabla Markdown
        if len(columns) > 0:
            # Crear el encabezado de la tabla
            header = "| " + " | ".join(columns) + " |"
            markdown_content.append(header)

            # Crear el separador
            separator = "| " + " | ".join(["---"] * len(columns)) + " |"
            markdown_content.append(separator)

            # Agregar las filas de datos
            for _, row in excel_data.iterrows():
                row_data = []
                for col in columns:
                    cell_value = str(row.get(col, "")).strip()
                    # Si la celda está vacía, usar un espacio
                    if not cell_value or cell_value == "nan":
                        cell_value = " "
                    # Escapar caracteres especiales de Markdown si es necesario
                    if "|" in cell_value:
                        cell_value = cell_value.replace("|", "\\|")
                    row_data.append(cell_value)

                row_line = "| " + " | ".join(row_data) + " |"
                markdown_content.append(row_line)

        # Escribir el archivo Markdown
        try:
            with open(output_md_filepath_abs, "w", encoding="utf-8") as f:
                f.write("\n".join(markdown_content))
            print(
                f"¡Éxito! Archivo Markdown de IO generado en: {output_md_filepath_abs}"
            )
            return True
        except IOError as e:
            print(
                f"Error al escribir el archivo Markdown '{output_md_filepath_abs}': {e}"
            )
            return False

    except FileNotFoundError:
        print(f"Error: El archivo '{excel_file_path}' no se encontró.")
        return False
    except pd.errors.EmptyDataError:
        print(f"Error: El archivo '{excel_file_path}' está vacío.")
        return False
    except Exception as e:
        print(f"Error al procesar el archivo Excel de IO: {e}")
        return False


def convert_excel_to_markdown_tables():
    """
    Busca un archivo Excel en el directorio configurado, lo procesa y genera
    un archivo Markdown con tablas filtradas en el directorio de resultados.
    """
    try:
        configs = load_configuration()
        working_directory = configs.get("working_directory")
        level2_configs = configs.get("level2", {})
        level3_configs = configs.get("level3", {})
        tags_exp_directory = level3_configs.get("tags_exp_directory", ".")
        resultados_exp_directory = level2_configs.get("resultados_exp_directory", ".")

        if not working_directory or not os.path.isdir(working_directory):
            print(
                f"Error: El directorio de trabajo '{working_directory}' no es válido."
            )
            return
    except Exception as e:
        print(f"Error al cargar la configuración: {e}")
        return

    working_directory_abs = os.path.abspath(working_directory)
    print(f"Usando directorio de trabajo: {working_directory_abs}")

    path_config = load_path_config()
    if not path_config:
        print("Error: No se pudo cargar la configuración de paths.")
        return

    tags_exp_dir_abs = os.path.join(working_directory_abs, tags_exp_directory)
    os.makedirs(tags_exp_dir_abs, exist_ok=True)
    print(f"Buscando archivos Excel en: {tags_exp_dir_abs}")

    excel_files = [
        f for f in os.listdir(tags_exp_dir_abs) if f.lower().endswith(".xlsx")
    ]
    excel_file_path = ""

    if len(excel_files) == 1:
        excel_file_path = os.path.join(tags_exp_dir_abs, excel_files[0])
        print(f"Archivo Excel encontrado automáticamente: {excel_file_path}")
    else:
        if len(excel_files) == 0:
            print(f"No se encontraron archivos Excel en '{tags_exp_dir_abs}'.")
        else:
            print(
                f"Se encontraron múltiples archivos Excel en '{tags_exp_dir_abs}'. Por favor seleccione uno."
            )

        root = tk.Tk()
        root.withdraw()
        excel_file_path = filedialog.askopenfilename(
            title="Seleccione el archivo Excel exportado de TIA Portal",
            filetypes=[("Excel files", "*.xlsx"), ("All files", "*.*")],
            initialdir=tags_exp_dir_abs,
        )
        if not excel_file_path:
            print("No se seleccionó ningún archivo Excel. Saliendo...")
            return

    print(f"Procesando archivo Excel: {excel_file_path}...")

    output_dir_abs = os.path.join(working_directory_abs, resultados_exp_directory)
    os.makedirs(output_dir_abs, exist_ok=True)
    output_md_filename = "Master IO Tags.md"
    output_md_filepath_abs = os.path.join(output_dir_abs, output_md_filename)

    markdown_content = []

    # Definición de las columnas y sus anchos para el formato Markdown
    md_header_names = ["Master Tag", "Type", "Data Type", "Description"]
    col_widths = {"Master Tag": 32, "Type": 6, "Data Type": 9, "Description": 71}

    # Crear el encabezado y separador Markdown
    header_parts = [f" {name:<{col_widths[name]}} " for name in md_header_names]
    markdown_table_header = f"|{'|'.join(header_parts)}|"

    separator_parts = [f" {'-'*col_widths[name]} " for name in md_header_names]
    markdown_table_separator = f"|{'|'.join(separator_parts)}|"

    # Obtener la lista de paths a procesar
    valid_paths = [path_entry["path"] for path_entry in path_config["paths"]]
    print(f"Paths configurados para procesar: {valid_paths}")

    try:
        # Leer el Excel exportado de TIA Portal
        excel_data = pd.read_excel(excel_file_path, sheet_name=0)

        # Verificar columnas requeridas
        excel_col_name = "Name"
        excel_col_path = "Path"
        excel_col_data_type = "Data Type"
        excel_col_comment = "Comment"

        excel_required_cols = [
            excel_col_name,
            excel_col_path,
            excel_col_data_type,
            excel_col_comment,
        ]

        missing_cols = [
            col for col in excel_required_cols if col not in excel_data.columns
        ]
        if missing_cols:
            print(
                f"Error: Columnas faltantes en el archivo Excel: {', '.join(missing_cols)}"
            )
            return

        # Organizar entradas por path y crear tablas para cada tipo
        for path_entry in path_config["paths"]:
            path_name = path_entry["path"]
            io_type = path_entry["type"]  # Input u Output

            # Filtrar datos por el path actual
            path_data = excel_data[excel_data[excel_col_path] == path_name]

            if path_data.empty:
                print(f"No se encontraron entradas para el path: {path_name}")
                continue

            # Agregar encabezado para este path
            markdown_content.append(f"## {path_name} ({io_type}s)\n")
            markdown_content.append(markdown_table_header)
            markdown_content.append(markdown_table_separator)

            # Procesar cada entrada en este path
            for _, row in path_data.iterrows():
                master_tag = str(row.get(excel_col_name, ""))
                data_type = str(row.get(excel_col_data_type, ""))
                comment_text = str(row.get(excel_col_comment, ""))
                description = f'"{comment_text}"'

                # Usar el tipo del path desde la configuración
                tag_type_for_md = io_type

                master_tag_cell = f"{master_tag:<{col_widths['Master Tag']}.{col_widths['Master Tag']}}"
                type_cell = (
                    f"{tag_type_for_md:<{col_widths['Type']}.{col_widths['Type']}}"
                )
                data_type_cell = (
                    f"{data_type:<{col_widths['Data Type']}.{col_widths['Data Type']}}"
                )
                description_cell = f"{description:<{col_widths['Description']}.{col_widths['Description']}}"

                md_row = f"| {master_tag_cell} | {type_cell} | {data_type_cell} | {description_cell} |"
                markdown_content.append(md_row)

            markdown_content.append("\n")  # Espacio después de cada tabla

    except FileNotFoundError:
        print(f"Error: El archivo '{excel_file_path}' no se encontró.")
        return
    except pd.errors.EmptyDataError:
        print(f"Error: El archivo '{excel_file_path}' está vacío.")
        return
    except Exception as e:
        print(f"Error al procesar el archivo Excel: {e}")
        return

    if markdown_content:
        try:
            with open(output_md_filepath_abs, "w", encoding="utf-8") as f:
                f.write("\n".join(markdown_content))
            print(f"¡Éxito! Archivo Markdown generado en: {output_md_filepath_abs}")
        except IOError as e:
            print(
                f"Error al escribir el archivo Markdown '{output_md_filepath_abs}': {e}"
            )
    else:
        print("No se generó contenido para el archivo Markdown.")


def main():
    """
    Función principal que ejecuta ambas conversiones:
    1. Convierte el Excel de tags de TIA Portal a 'Master IO Tags.md'
    2. Convierte el Excel de IO desde esquema eléctrico a 'IO Adapted.md'
    """
    print("=== Conversión de archivos Excel a Markdown ===\n")

    # 1. Convertir Excel de tags de TIA Portal
    print("1. Convirtiendo Excel de tags de TIA Portal...")
    convert_excel_to_markdown_tables()

    print("\n" + "=" * 50 + "\n")

    # 2. Convertir Excel de IO desde esquema eléctrico
    print("2. Convirtiendo Excel de IO desde esquema eléctrico...")
    convert_io_excel_to_markdown()

    print("\n=== Proceso completado ===")


if __name__ == "__main__":
    main()
