#!/usr/bin/env python3
"""
Test script para verificar la detección de cambios basada en hash.

Este script demuestra cómo el sistema detecta cambios en archivos XML
utilizando hash SHA256 en lugar de solo tiempo/tamaño de archivo.
"""

import os
import json
import hashlib
import tempfile
import shutil
from datetime import datetime


def calculate_file_hash(filepath):
    """Calcula el hash SHA256 de un archivo."""
    try:
        sha256_hash = hashlib.sha256()
        with open(filepath, "rb") as f:
            for chunk in iter(lambda: f.read(4096), b""):
                sha256_hash.update(chunk)
        return sha256_hash.hexdigest()
    except Exception as e:
        print(f"Error calculando hash de {filepath}: {e}")
        return None


def create_test_xml(content, filepath):
    """Crea un archivo XML de prueba con el contenido especificado."""
    with open(filepath, "w", encoding="utf-8") as f:
        f.write(content)


def create_test_json(xml_filepath, json_filepath):
    """Crea un archivo JSON de prueba con metadatos del XML."""
    xml_hash = calculate_file_hash(xml_filepath)
    xml_mtime = os.path.getmtime(xml_filepath)
    xml_size = os.path.getsize(xml_filepath)

    json_data = {
        "block_name": "Test_Block",
        "block_type": "FC",
        "language": "LAD",
        "source_xml_mod_time": xml_mtime,
        "source_xml_size": xml_size,
        "source_xml_hash": xml_hash,
        "interface": {},
        "networks": [],
    }

    with open(json_filepath, "w", encoding="utf-8") as f:
        json.dump(json_data, f, indent=4)

    return json_data


def test_hash_detection():
    """Prueba la detección de cambios basada en hash."""
    print("=== Test de Detección de Cambios por Hash ===\n")

    # Crear directorio temporal
    with tempfile.TemporaryDirectory() as temp_dir:
        xml_file = os.path.join(temp_dir, "test_block.xml")
        json_file = os.path.join(temp_dir, "test_block_processed.json")

        # Paso 1: Crear XML original
        original_content = """<?xml version="1.0" encoding="UTF-8"?>
<Document>
    <SW.Blocks.FC ID="A">
        <AttributeList>
            <Name>Test_Block</Name>
            <Number>100</Number>
            <ProgrammingLanguage>LAD</ProgrammingLanguage>
        </AttributeList>
        <ObjectList>
            <NetworkSource />
        </ObjectList>
    </SW.Blocks.FC>
</Document>"""

        create_test_xml(original_content, xml_file)
        original_hash = calculate_file_hash(xml_file)
        print(f"1. XML original creado")
        print(f"   Hash: {original_hash[:16]}...")
        print(f"   Tamaño: {os.path.getsize(xml_file)} bytes")

        # Paso 2: Crear JSON con metadatos
        json_data = create_test_json(xml_file, json_file)
        print(f"\n2. JSON con metadatos creado")
        print(f"   Hash almacenado: {json_data['source_xml_hash'][:16]}...")

        # Paso 3: Simular verificación - archivo sin cambios
        current_hash = calculate_file_hash(xml_file)
        hash_match = json_data["source_xml_hash"] == current_hash
        print(f"\n3. Verificación sin cambios:")
        print(f"   Hash actual: {current_hash[:16]}...")
        print(f"   ¿Hash coincide?: {hash_match}")
        print(f"   → {'SALTAR procesamiento' if hash_match else 'PROCESAR archivo'}")

        # Paso 4: Modificar archivo manteniendo mismo tamaño y tiempo
        print(f"\n4. Modificando XML (cambio sutil)...")
        modified_content = original_content.replace(
            "Test_Block", "Test_Blck"
        )  # Cambio sutil

        # Guardar tiempo original
        original_mtime = os.path.getmtime(xml_file)

        create_test_xml(modified_content, xml_file)

        # Restaurar tiempo original (simular que el timestamp no cambió)
        os.utime(xml_file, (original_mtime, original_mtime))

        new_size = os.path.getsize(xml_file)
        new_mtime = os.path.getmtime(xml_file)
        new_hash = calculate_file_hash(xml_file)

        print(f"   Nuevo hash: {new_hash[:16]}...")
        print(f"   Nuevo tamaño: {new_size} bytes")
        print(
            f"   Tiempo modificación: {abs(new_mtime - json_data['source_xml_mod_time']) < 0.001}"
        )

        # Paso 5: Verificar detección por diferentes métodos
        print(f"\n5. Comparación de métodos de detección:")

        # Método tradicional (tiempo + tamaño)
        time_match = abs(new_mtime - json_data["source_xml_mod_time"]) < 0.001
        size_match = new_size == json_data["source_xml_size"]
        traditional_would_skip = time_match and size_match

        # Método por hash
        hash_would_skip = new_hash == json_data["source_xml_hash"]

        print(f"   Método tradicional (tiempo+tamaño):")
        print(f"     ¿Tiempo coincide?: {time_match}")
        print(f"     ¿Tamaño coincide?: {size_match}")
        print(f"     → {'SALTAR' if traditional_would_skip else 'PROCESAR'}")

        print(f"   Método por hash:")
        print(f"     ¿Hash coincide?: {hash_would_skip}")
        print(f"     → {'SALTAR' if hash_would_skip else 'PROCESAR'}")

        print(f"\n6. Resultado:")
        if traditional_would_skip and not hash_would_skip:
            print(f"   ✅ HASH DETECTÓ CAMBIO que el método tradicional PERDIÓ")
            print(f"   🔄 El archivo será regenerado correctamente")
        elif not traditional_would_skip and not hash_would_skip:
            print(f"   ✅ Ambos métodos detectaron el cambio")
        elif traditional_would_skip and hash_would_skip:
            print(f"   ✅ Ambos métodos indican que no hay cambios")
        else:
            print(f"   ⚠️  Situación inesperada")

        # Paso 6: Mostrar contenidos para verificación
        print(f"\n7. Verificación de contenido:")
        print(f"   Contenido original tenía: 'Test_Block'")
        print(f"   Contenido nuevo tiene: 'Test_Blck'")

        with open(xml_file, "r", encoding="utf-8") as f:
            content = f.read()
            has_original = "Test_Block" in content
            has_modified = "Test_Blck" in content
            print(f"   ¿Contiene 'Test_Block'?: {has_original}")
            print(f"   ¿Contiene 'Test_Blck'?: {has_modified}")


if __name__ == "__main__":
    test_hash_detection()
