#!/usr/bin/env python3
"""
Test específico para demostrar casos donde el hash detecta cambios
que el método tradicional (tiempo + tamaño) podría perder.
"""

import os
import json
import hashlib
import tempfile
import time


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 test_subtle_changes():
    """Demuestra detección de cambios sutiles que mantienen el mismo tamaño."""
    print("=== Test: Cambios Sutiles con Mismo Tamaño ===\n")

    with tempfile.TemporaryDirectory() as temp_dir:
        xml_file = os.path.join(temp_dir, "test.xml")

        # Crear contenido original de exactamente el mismo tamaño
        original = """<?xml version="1.0"?>
<Block>
    <Name>MotorControl_01</Name>
    <Status>Active</Status>
</Block>"""

        # Crear contenido modificado del mismo tamaño (cambiar solo algunos caracteres)
        modified = """<?xml version="1.0"?>
<Block>
    <Name>MotorControl_02</Name>
    <Status>Active</Status>
</Block>"""

        # Verificar que tienen el mismo tamaño
        assert len(original) == len(
            modified
        ), "Los contenidos deben tener el mismo tamaño"

        # Paso 1: Crear archivo original
        with open(xml_file, "w", encoding="utf-8") as f:
            f.write(original)

        original_hash = calculate_file_hash(xml_file)
        original_size = os.path.getsize(xml_file)
        original_mtime = os.path.getmtime(xml_file)

        print(f"1. Archivo original:")
        print(f"   Contenido: MotorControl_01")
        print(f"   Hash: {original_hash[:16]}...")
        print(f"   Tamaño: {original_size} bytes")

        # Simular JSON con metadatos
        json_data = {
            "source_xml_hash": original_hash,
            "source_xml_size": original_size,
            "source_xml_mod_time": original_mtime,
        }

        # Paso 2: Esperar un poco y modificar archivo manteniendo tamaño
        time.sleep(0.1)  # Pequeña pausa

        with open(xml_file, "w", encoding="utf-8") as f:
            f.write(modified)

        # Restaurar tiempo de modificación original
        os.utime(xml_file, (original_mtime, original_mtime))

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

        print(f"\n2. Archivo modificado:")
        print(f"   Contenido: MotorControl_02")
        print(f"   Hash: {new_hash[:16]}...")
        print(f"   Tamaño: {new_size} bytes")
        print(
            f"   Tiempo: {'Igual' if abs(new_mtime - original_mtime) < 0.001 else 'Diferente'}"
        )

        # Paso 3: Comparar métodos de detección
        print(f"\n3. Detección de cambios:")

        # Método tradicional
        time_match = abs(new_mtime - json_data["source_xml_mod_time"]) < 0.001
        size_match = new_size == json_data["source_xml_size"]
        traditional_detects_change = not (time_match and size_match)

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

        print(f"   Método tradicional:")
        print(f"     Tiempo coincide: {time_match}")
        print(f"     Tamaño coincide: {size_match}")
        print(f"     Detecta cambio: {traditional_detects_change}")

        print(f"   Método por hash:")
        print(f"     Hash coincide: {new_hash == json_data['source_xml_hash']}")
        print(f"     Detecta cambio: {hash_detects_change}")

        # Resultado
        print(f"\n4. Resultado:")
        if not traditional_detects_change and hash_detects_change:
            print(f"   🎯 HASH DETECTÓ CAMBIO que método tradicional PERDIÓ")
            print(f"   ✅ Sin hash: archivo NO se regeneraría (ERROR)")
            print(f"   ✅ Con hash: archivo SÍ se regenerará (CORRECTO)")
        elif traditional_detects_change and hash_detects_change:
            print(f"   ✅ Ambos métodos detectaron el cambio correctamente")
        else:
            print(
                f"   ℹ️  Resultado: tradicional={traditional_detects_change}, hash={hash_detects_change}"
            )

        return not traditional_detects_change and hash_detects_change


def test_same_size_different_content():
    """Test con contenidos completamente diferentes pero mismo tamaño."""
    print("\n" + "=" * 50)
    print("=== Test: Contenido Diferente, Mismo Tamaño ===\n")

    with tempfile.TemporaryDirectory() as temp_dir:
        xml_file = os.path.join(temp_dir, "test.xml")

        # Contenidos de igual longitud pero diferentes
        content1 = "<Root><Item>AAAAAAAAAA</Item></Root>"  # 33 chars
        content2 = "<Root><Item>BBBBBBBBBB</Item></Root>"  # 33 chars

        assert len(content1) == len(content2), "Deben tener igual tamaño"

        # Crear archivo con contenido 1
        with open(xml_file, "w", encoding="utf-8") as f:
            f.write(content1)

        hash1 = calculate_file_hash(xml_file)
        size1 = os.path.getsize(xml_file)
        mtime1 = os.path.getmtime(xml_file)

        # Cambiar a contenido 2 manteniendo tiempo
        time.sleep(0.1)
        with open(xml_file, "w", encoding="utf-8") as f:
            f.write(content2)
        os.utime(xml_file, (mtime1, mtime1))

        hash2 = calculate_file_hash(xml_file)
        size2 = os.path.getsize(xml_file)
        mtime2 = os.path.getmtime(xml_file)

        print(f"Contenido 1: {content1[:20]}...")
        print(f"Contenido 2: {content2[:20]}...")
        print(f"Tamaños: {size1} = {size2} ({'✓' if size1 == size2 else '✗'})")
        print(f"Tiempos: {'iguales' if abs(mtime2 - mtime1) < 0.001 else 'diferentes'}")
        print(f"Hashes: {'iguales' if hash1 == hash2 else 'diferentes'}")

        would_skip_traditional = (size1 == size2) and (abs(mtime2 - mtime1) < 0.001)
        would_skip_hash = hash1 == hash2

        print(
            f"\nSin hash: {'SALTARÍA procesamiento' if would_skip_traditional else 'procesaría'}"
        )
        print(
            f"Con hash: {'saltaría procesamiento' if would_skip_hash else 'PROCESARÍA'}"
        )

        if would_skip_traditional and not would_skip_hash:
            print("🎯 El hash evita saltar un archivo que SÍ cambió")
            return True

        return False


if __name__ == "__main__":
    print("Ejecutando tests de detección de cambios por hash...\n")

    test1_result = test_subtle_changes()
    test2_result = test_same_size_different_content()

    print("\n" + "=" * 50)
    print("=== RESUMEN ===")
    print(
        f"Test 1 (cambios sutiles): {'HASH ÚTIL' if test1_result else 'ambos métodos iguales'}"
    )
    print(
        f"Test 2 (mismo tamaño): {'HASH ÚTIL' if test2_result else 'ambos métodos iguales'}"
    )

    if test1_result or test2_result:
        print("\n✅ El hash SHA256 mejora la detección de cambios")
        print("✅ Evita regeneraciones innecesarias Y perdida de cambios reales")
    else:
        print("\n✓ Ambos métodos funcionaron igual en estos tests")
