# -*- coding: utf-8 -*-
"""
TEITAN MASTER RESCUE FINALIZER — V5.2.1 (SECURE KINGSTON AUDITED REVISION)
Ubicacion: E:\\TEITAN_RESCUE_OUTPUT\\TOOLS\\finalize_master_v521.py

Cumplimiento estricto de las garantias pendientes de la orden V5.2.1:
1. AISLAMIENTO PREVIO A CUALQUIER OPERACION DE ENTRADA/SALIDA:
   - Toda ruta recuperada (incluyendo la del registro ficticio) se somete a
     validate_staged_path_isolation() ANTES de llamar os.path.exists(),
     os.path.getsize(), open() o calcular su SHA-256.
   - Rechazo tajante de rutas hacia C:, rutas relativas, symlinks o junctions fuera de Kingston.
2. LIMPIEZA CENTRALIZADA DE TEMPORALES:
   - Todo el proceso de construccion en run_finalize() se encuentra protegido por
     un bloque centralizado try...except...finally.
   - Ante CUALQUIER excepcion, interrupcion o fallo de streaming/hash, se cierran
     todos los descriptores abiertos y se elimina unica y exclusivamente el archivo
     temporal unico generado en esa ejecucion concreta, dejando intactos temporales historicos.
   - Si la eliminacion del temporal falla, se registra en consola su ruta absoluta exacta.
3. CONTRATO DE NO-SOBRESCRITURA ATOMICA Y REPORTE SEGURO:
   - Si 'teitan.zip' ya existe, la ejecucion se bloquea sin alterarlo.
   - Verificacion de no-preexistencia en publicacion usando os.rename() garantizando atomicidad.
   - Generacion de 'FINAL_MASTER_REPORT.json' con creacion exclusiva atómica (open(..., "x"))
     para prevenir condiciones de carrera y proteger reportes preexistentes.
4. VALIDACION EXHAUSTIVA DE CONTENIDO Y MANIFIESTO:
   - Validacion del SHA-256 historico del nucleo:
     40DA5AB6568DEABF9E60D70EAF96321632FBDBF4B9B646CA392BDC3BEF1EC199.
   - Validacion de tamano descomprimido (ZipInfo.file_size) de las 147,903 entradas
     del nucleo contra la columna 'bytes' de SQLite sin descomprimir en disco.
   - Verificacion anticipada de que los 2,387 arcnames de AR88 son estrictamente unicos
     y tienen 0 colision con las entradas del nucleo.
"""

import os
import sys
import time
import shutil
import zipfile
import hashlib
import json
import subprocess
import uuid
import sqlite3

EXPECTED_KINGSTON_SERIAL_SUBSTR = "0026_B728_3F45_1265"
TARGET_DRIVE = "E:\\"
RESCUE_ROOT = os.path.join(TARGET_DRIVE, "TEITAN_RESCUE_OUTPUT")
STAGE_ROOT = os.path.join(RESCUE_ROOT, "STAGED_COPIES")
CHECKPOINT_DB_PATH = os.path.join(RESCUE_ROOT, "stage_checkpoint.sqlite")
CORE_ZIP_PATH = os.path.join(RESCUE_ROOT, "teitan_core.zip")
MASTER_ZIP_PATH = os.path.join(RESCUE_ROOT, "teitan.zip")
FINAL_REPORT_PATH = os.path.join(RESCUE_ROOT, "FINAL_MASTER_REPORT.json")

EXPECTED_CORE_COUNT = 147903
EXPECTED_AR88_COUNT = 2387
EXPECTED_TOTAL_COUNT = 150290

EXPECTED_CORE_SHA256 = "40DA5AB6568DEABF9E60D70EAF96321632FBDBF4B9B646CA392BDC3BEF1EC199"
EXACT_FAKE_NORM_SOURCE = "c:\\disco_roto_no_existe_fake.dat"
EXACT_COLLIDING_NORM_SOURCE = "c:\\xampp\\htdocs\\digital optimus\\.gitignore"

SAFETY_MARGIN_BYTES = 15 * 1024 * 1024 * 1024  # 15 GiB
SAFE_FALLBACK_DATE_TIME = (2026, 10, 29, 12, 0, 0)

def verify_kingston_hardware():
    """Valida fisicamente que E: resida en KINGSTON SNV3S1000G con el serial esperado."""
    ps_cmd = "Get-Partition -DriveLetter E | Get-Disk | Select-Object FriendlyName, SerialNumber, Number | ConvertTo-Json"
    try:
        proc = subprocess.run(["powershell", "-NoProfile", "-Command", ps_cmd], capture_output=True, text=True, timeout=10)
        if proc.returncode == 0 and proc.stdout.strip():
            disk_info = json.loads(proc.stdout)
            friendly = disk_info.get("FriendlyName", "")
            serial = disk_info.get("SerialNumber", "")
            if "KINGSTON" not in friendly or EXPECTED_KINGSTON_SERIAL_SUBSTR not in serial:
                return False, f"El volumen E: reside en {friendly} (S/N: {serial}), NO en el Kingston esperado."
            return True, f"Hardware Kingston verificado ({friendly}, S/N: {serial})"
        else:
            return False, "No fue posible consultar la procedencia fisica del volumen E:."
    except Exception as e:
        return False, f"Error validando hardware: {e}"

def validate_staged_path_isolation(staged_path, allowed_stage_root=None):
    """
    Aislamiento fisico estricto:
    - Comprueba que la ruta este dentro de allowed_stage_root (por defecto STAGE_ROOT).
    - Resuelve enlaces simbolicos / junctions con realpath.
    - Rechaza cualquier ruta que intente escapar o leer de C:.
    """
    if allowed_stage_root is None:
        allowed_stage_root = STAGE_ROOT

    # Rechazo preliminar de C: antes de realpath para evitar accesos indebidos
    norm_pre = os.path.normcase(os.path.abspath(staged_path))
    if norm_pre.startswith("c:"):
        return False, f"Intento critico de lectura hacia SSD C:: {staged_path}"

    norm_root = os.path.normcase(os.path.realpath(allowed_stage_root))
    norm_target = os.path.normcase(os.path.realpath(staged_path))

    if not norm_target.startswith(norm_root + os.sep) and norm_target != norm_root:
        return False, f"Ruta fuera de staging autorizado: {staged_path} -> {norm_target}"

    if norm_target.startswith("c:"):
        return False, f"Intento critico de lectura hacia SSD C: tras resolucion: {staged_path}"

    return True, "OK"

def validate_zip_arcname(arcname):
    """Valida que el nombre de archivo dentro del ZIP sea seguro y libre de directory traversal."""
    if os.path.isabs(arcname):
        return False, f"Ruta absoluta en ZIP no permitida: {arcname}"
    parts = arcname.replace('\\', '/').split('/')
    if '..' in parts or '.' in parts:
        return False, f"Directory traversal en ZIP no permitido: {arcname}"
    if arcname.startswith('/') or arcname.startswith('\\'):
        return False, f"Barra inicial en ZIP no permitida: {arcname}"
    return True, "OK"

def get_sanitized_zip_date_time(mtime_timestamp):
    """
    Convierte mtime a tupla ZIP (Y, M, D, H, M, S) de forma segura.
    Si falla time.localtime() por desbordamiento en Windows o queda fuera de 1980..2107,
    retorna SAFE_FALLBACK_DATE_TIME y registra el motivo.
    """
    try:
        dt = time.localtime(mtime_timestamp)
        if dt.tm_year < 1980 or dt.tm_year > 2107:
            return SAFE_FALLBACK_DATE_TIME, f"Year out of bounds ({dt.tm_year})"
        return (dt.tm_year, dt.tm_mon, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec), None
    except Exception as e:
        return SAFE_FALLBACK_DATE_TIME, f"time.localtime failed: {e}"

def calculate_sha256(filepath):
    sha = hashlib.sha256()
    with open(filepath, "rb") as f:
        while chunk := f.read(4 * 1024 * 1024):
            sha.update(chunk)
    return sha.hexdigest().upper()

def run_preflight(db_path=None, core_zip_path=None, target_drive=None, stage_root=None, master_zip_path=None, final_report_path=None):
    """
    Modo Preflight completo de V5.2.1.
    Garantiza aislamiento estricto antes de cualquier lectura, verifica integridad,
    tamanios descomprimidos contra SQLite, unicidad absoluta y disponibilidad de espacio.
    """
    if db_path is None: db_path = CHECKPOINT_DB_PATH
    if core_zip_path is None: core_zip_path = CORE_ZIP_PATH
    if target_drive is None: target_drive = TARGET_DRIVE
    if stage_root is None: stage_root = STAGE_ROOT
    if master_zip_path is None: master_zip_path = MASTER_ZIP_PATH
    if final_report_path is None: final_report_path = FINAL_REPORT_PATH

    print("=" * 68)
    print("  TEITAN FINALIZER V5.2.1 — MODO PREFLIGHT (AUDITORIA RIGUROSA)")
    print("=" * 68)

    # 1. Comprobacion de destino maestro no preexistente
    if os.path.exists(master_zip_path):
        print(f"[FAIL] teitan.zip ya existe en destino ({master_zip_path}). Prohibido sobrescribir.")
        return False
    if os.path.exists(final_report_path):
        print(f"[FAIL] FINAL_MASTER_REPORT.json ya existe en destino ({final_report_path}). Prohibido sobrescribir.")
        return False
    print("[PASS] 1. Contrato de no-sobrescritura: teitan.zip y reporte final no preexisten.")

    # 2. Hardware Kingston (solo en ejecucion sobre E:)
    if target_drive.upper().startswith("E:"):
        ok_hw, msg_hw = verify_kingston_hardware()
        if not ok_hw:
            print(f"[FAIL] {msg_hw}")
            return False
        print(f"[PASS] 2. {msg_hw}")
    else:
        print("[INFO] 2. Modo sandbox / prueba: omitiendo verificacion directa de hardware Kingston.")

    # 3. Checkpoint SQLite integridad
    if not os.path.exists(db_path):
        print(f"[FAIL] No existe base de checkpoint: {db_path}")
        return False

    uri_db = f"file:{os.path.abspath(db_path).replace(os.sep, '/')}?mode=ro"
    conn = sqlite3.connect(uri_db, uri=True)
    cur = conn.cursor()
    cur.execute("PRAGMA quick_check;")
    qc = cur.fetchone()[0]
    if qc != "ok":
        print(f"[FAIL] Checkpoint corrupto: {qc}")
        conn.close()
        return False
    print(f"[PASS] 3. Checkpoint SQLite integro (PRAGMA quick_check = ok).")

    # 4. Resolucion exacta del registro ficticio con AISLAMIENTO PREVIO ESTRICTO (Garantia 1)
    cur.execute("SELECT norm_source, original_source, staged_path, bytes, sha256 FROM file_checkpoints WHERE norm_source = ?", (EXACT_FAKE_NORM_SOURCE,))
    fake_rows = cur.fetchall()
    if len(fake_rows) != 1:
        print(f"[FAIL] Se esperaba exactamente 1 registro ficticio con norm_source='{EXACT_FAKE_NORM_SOURCE}', encontrados: {len(fake_rows)}")
        conn.close()
        return False
    fake_rec = fake_rows[0]
    fake_staged_path = fake_rec[2]

    # GARANTIA 1: Validar aislamiento antes de cualquier lectura o existencia
    ok_iso, msg_iso = validate_staged_path_isolation(fake_staged_path, allowed_stage_root=stage_root)
    if not ok_iso:
        print(f"[FAIL] Violacion de aislamiento en staged_path del registro ficticio: {msg_iso}")
        conn.close()
        return False

    # Validar que comparte staged_path exclusivamente con .gitignore
    cur.execute("SELECT norm_source, original_source, staged_path, bytes, sha256 FROM file_checkpoints WHERE staged_path = ?", (fake_staged_path,))
    colliding_rows = cur.fetchall()
    if len(colliding_rows) != 2:
        print(f"[FAIL] El staged_path del registro ficticio no tiene exactamente 2 entradas: {len(colliding_rows)}")
        conn.close()
        return False

    norm_sources_in_collision = set(r[0] for r in colliding_rows)
    if norm_sources_in_collision != {EXACT_FAKE_NORM_SOURCE, EXACT_COLLIDING_NORM_SOURCE}:
        print(f"[FAIL] Colision en staged_path involucra registros no autorizados: {norm_sources_in_collision}")
        conn.close()
        return False

    # Validar que ambos tienen 733 bytes y mismo sha256
    if colliding_rows[0][3] != 733 or colliding_rows[1][3] != 733 or colliding_rows[0][4] != colliding_rows[1][4]:
        print(f"[FAIL] Metadatos de la colision no coinciden con los 733 bytes o hash documentado.")
        conn.close()
        return False

    # Aislamiento comprobado: ahora si validar existencia fisica, tamano y hash
    if not os.path.exists(fake_staged_path) or os.path.getsize(fake_staged_path) != 733:
        print(f"[FAIL] El archivo fisico en staging no existe o no tiene 733 bytes: {fake_staged_path}")
        conn.close()
        return False

    actual_git_hash = calculate_sha256(fake_staged_path)
    if actual_git_hash != fake_rec[4]:
        print(f"[FAIL] Hash real de .gitignore en staging difiere del checkpoint.")
        conn.close()
        return False

    # Validar que NO existen otros duplicados en staged_path en toda la base
    cur.execute("SELECT staged_path, count(*) as c FROM file_checkpoints GROUP BY staged_path HAVING c > 1")
    all_dupes = cur.fetchall()
    if len(all_dupes) != 1:
        print(f"[FAIL] Existen otras colisiones de staged_path en SQLite no resueltas: {all_dupes}")
        conn.close()
        return False
    print(f"[PASS] 4. Registro ficticio auditado con aislamiento previo validado.")

    # 5. Integridad exacta del nucleo teitan_core.zip
    if not os.path.exists(core_zip_path):
        print(f"[FAIL] No existe teitan_core.zip: {core_zip_path}")
        conn.close()
        return False

    actual_core_sha256 = calculate_sha256(core_zip_path)
    if core_zip_path == CORE_ZIP_PATH:
        if actual_core_sha256 != EXPECTED_CORE_SHA256:
            print(f"[FAIL] Hash de teitan_core.zip difiere del esperado: {actual_core_sha256} != {EXPECTED_CORE_SHA256}")
            conn.close()
            return False
        print(f"[PASS] 5. SHA-256 de teitan_core.zip coincide al 100% ({actual_core_sha256}).")
    else:
        print(f"[INFO] 5. teitan_core.zip (sandbox) SHA-256: {actual_core_sha256}")

    # 6. Validacion de tamanos descomprimidos del nucleo contra SQLite (Garantia 4)
    core_zf = zipfile.ZipFile(core_zip_path, 'r')
    core_infolist = core_zf.infolist()
    core_count = len(core_infolist)
    core_unique = len(set(zi.filename for zi in core_infolist))

    expected_core_c = EXPECTED_CORE_COUNT if core_zip_path == CORE_ZIP_PATH else core_count
    if core_count != expected_core_c or core_unique != expected_core_c:
        print(f"[FAIL] Entradas en teitan_core.zip: {core_count} (unicas: {core_unique}), esperadas: {expected_core_c}")
        core_zf.close()
        conn.close()
        return False

    cur.execute("SELECT original_source, bytes FROM file_checkpoints WHERE norm_source NOT LIKE ? AND norm_source != ?", (r'%ar88_sandbox%', EXACT_FAKE_NORM_SOURCE))
    db_core_rows = cur.fetchall()

    if core_zip_path == CORE_ZIP_PATH:
        if len(db_core_rows) != EXPECTED_CORE_COUNT:
            print(f"[FAIL] SQLite registros legitimos de nucleo ({len(db_core_rows)}) != {EXPECTED_CORE_COUNT}")
            core_zf.close()
            conn.close()
            return False

    db_core_size_map = {}
    for r in db_core_rows:
        arc = os.path.splitdrive(r[0])[1].lstrip('\\/').replace('\\', '/')
        db_core_size_map[arc] = r[1]

    # Validacion rapida de tamanos descomprimidos sin extraer a disco
    size_mismatch_count = 0
    for zi in core_infolist:
        expected_bytes = db_core_size_map.get(zi.filename)
        if expected_bytes is None:
            print(f"[FAIL] Entrada {zi.filename} en ZIP del nucleo no encontrada en SQLite.")
            core_zf.close()
            conn.close()
            return False
        if zi.file_size != expected_bytes:
            print(f"[FAIL] Discrepancia en tamano de miembro {zi.filename}: ZIP {zi.file_size} != SQLite {expected_bytes}")
            size_mismatch_count += 1
            if size_mismatch_count >= 5:
                break

    if size_mismatch_count > 0:
        print(f"[FAIL] Se detectaron discrepancias en tamanios descomprimidos del nucleo.")
        core_zf.close()
        conn.close()
        return False

    core_arcnames_set = set(zi.filename for zi in core_infolist)
    core_zf.close()
    print(f"[PASS] 6. Cobertura y tamanos de los 147,903 miembros del nucleo verificados contra SQLite.")

    # 7. Aislamiento fisico, no-colision y comprobacion de AR88 (Garantias 1 y 4)
    cur.execute("SELECT norm_source, original_source, staged_path, bytes, sha256 FROM file_checkpoints WHERE norm_source LIKE ? AND status = 'VERIFIED' ORDER BY original_source", (r'%ar88_sandbox%',))
    ar88_rows = cur.fetchall()

    expected_ar88_c = EXPECTED_AR88_COUNT if db_path == CHECKPOINT_DB_PATH else len(ar88_rows)
    if len(ar88_rows) != expected_ar88_c:
        print(f"[FAIL] Registros de AR88 en SQLite ({len(ar88_rows)}) != {expected_ar88_c}")
        conn.close()
        return False

    ar88_arcnames = []
    ar88_total_bytes = 0
    for r in ar88_rows:
        orig_s = r[1]
        staged_p = r[2]
        exp_bytes = r[3]

        # GARANTIA 1: Aislamiento antes de tocar el sistema de archivos
        ok_iso, msg_iso = validate_staged_path_isolation(staged_p, allowed_stage_root=stage_root)
        if not ok_iso:
            print(f"[FAIL] Violacion de aislamiento en AR88: {msg_iso}")
            conn.close()
            return False

        arcname = os.path.splitdrive(orig_s)[1].lstrip('\\/').replace('\\', '/')
        ok_arc, msg_arc = validate_zip_arcname(arcname)
        if not ok_arc:
            print(f"[FAIL] Arcname invalido en AR88: {msg_arc}")
            conn.close()
            return False

        ar88_arcnames.append(arcname)

        if not os.path.exists(staged_p) or os.path.getsize(staged_p) != exp_bytes:
            print(f"[FAIL] Archivo AR88 falta o difiere en tamano: {staged_p}")
            conn.close()
            return False

        ar88_total_bytes += exp_bytes

    # GARANTIA 4: Unicidad absoluta de arcnames de AR88 y ausencia total de solapamiento con el nucleo
    if len(ar88_arcnames) != len(set(ar88_arcnames)):
        print(f"[FAIL] Se detectaron arcnames duplicados internamente en AR88.")
        conn.close()
        return False

    overlap = set(ar88_arcnames).intersection(core_arcnames_set)
    if overlap:
        print(f"[FAIL] Se detecto solapamiento de nombres entre AR88 y el nucleo: {len(overlap)} colisiones.")
        conn.close()
        return False

    print(f"[PASS] 7. Aislamiento, unicidad absoluta y no-colision de {len(ar88_rows)} archivos AR88 ({ar88_total_bytes / (1024**3):.2f} GiB).")

    # 8. Total Reconciliado (Exactamente 150,290)
    if db_path == CHECKPOINT_DB_PATH and core_zip_path == CORE_ZIP_PATH:
        cur.execute("SELECT count(*) FROM file_checkpoints WHERE norm_source != ?", (EXACT_FAKE_NORM_SOURCE,))
        total_legit = cur.fetchone()[0]
        if total_legit != EXPECTED_TOTAL_COUNT:
            print(f"[FAIL] Total de archivos legitimos reconciliados ({total_legit}) != {EXPECTED_TOTAL_COUNT}")
            conn.close()
            return False
        print(f"[PASS] 8. Reconciliacion exacta de inventario: exactamente {total_legit} archivos legitimos.")

    # 9. Calculo dinamico conservador de espacio
    core_bytes = os.path.getsize(core_zip_path)
    required_space = core_bytes + ar88_total_bytes + (2 * 1024 * 1024 * 1024) + SAFETY_MARGIN_BYTES
    free_bytes = shutil.disk_usage(target_drive).free

    print(f"[INFO] Espacio libre en destino: {free_bytes / (1024**3):.2f} GiB")
    print(f"[INFO] Espacio conservador requerido: {required_space / (1024**3):.2f} GiB (incluye 15 GiB de margen)")

    if free_bytes < required_space:
        print(f"[FAIL] Espacio insuficiente en destino ({free_bytes / (1024**3):.2f} GiB < {required_space / (1024**3):.2f} GiB)")
        conn.close()
        return False
    print(f"[PASS] 9. Evaluacion dinamica de espacio libre aprobada.")

    conn.close()
    print("=" * 68)
    print("RESULTADO PREFLIGHT V5.2.1: APTO PARA FINALIZACION (--finalize)")
    print("=" * 68)
    return True

def run_finalize(db_path=None, core_zip_path=None, target_drive=None, stage_root=None, master_zip_path=None, final_report_path=None):
    """
    Modo Finalize completo de V5.2.1.
    Ejecuta el preflight estricto y procede con la construccion del maestro bajo proteccion
    centralizada try...except...finally garantizando limpieza segura de temporales
    y publicacion atomica sin riesgo de sobrescritura ni estados residuales.
    """
    if db_path is None: db_path = CHECKPOINT_DB_PATH
    if core_zip_path is None: core_zip_path = CORE_ZIP_PATH
    if target_drive is None: target_drive = TARGET_DRIVE
    if stage_root is None: stage_root = STAGE_ROOT
    if master_zip_path is None: master_zip_path = MASTER_ZIP_PATH
    if final_report_path is None: final_report_path = FINAL_REPORT_PATH

    print("=" * 68)
    print("  TEITAN FINALIZER V5.2.1 — MODO FINALIZE (CONSTRUCCION DEFINITIVA)")
    print("=" * 68)

    # 1. Preflight obligatorio estricto
    if not run_preflight(db_path, core_zip_path, target_drive, stage_root, master_zip_path, final_report_path):
        print("[BLOQUEO] Preflight fallo. Abortando finalizacion.")
        sys.exit(1)

    # 2. Doble guardia de no-sobrescritura
    if os.path.exists(master_zip_path):
        print(f"[BLOQUEO CRITICO] teitan.zip ya existe en {master_zip_path}. Prohibido sobrescribir.")
        sys.exit(1)
    if os.path.exists(final_report_path):
        print(f"[BLOQUEO CRITICO] {final_report_path} ya existe. Prohibido sobrescribir.")
        sys.exit(1)

    # 3. Obtener registros de AR88 desde SQLite en modo ro
    uri_db = f"file:{os.path.abspath(db_path).replace(os.sep, '/')}?mode=ro"
    conn = sqlite3.connect(uri_db, uri=True)
    cur = conn.cursor()
    cur.execute("SELECT norm_source, original_source, staged_path, bytes, sha256 FROM file_checkpoints WHERE norm_source LIKE ? AND status = 'VERIFIED' ORDER BY original_source", (r'%ar88_sandbox%',))
    ar88_entries = cur.fetchall()
    conn.close()

    # 4. Crear archivo temporal unico en destino
    temp_dir = os.path.dirname(master_zip_path)
    temp_master_zip = os.path.join(temp_dir, f"teitan.zip.finalizing_{os.getpid()}_{uuid.uuid4().hex}.zip")
    print(f"\nDestino Temporal: {temp_master_zip}")
    print(f"Destino Definitivo: {master_zip_path}")

    zf_active = None
    build_successful = False

    # GARANTIA 2: Manejo centralizado de errores y limpieza exhaustiva
    try:
        # Paso A: Clonar teitan_core.zip como base del maestro
        print("\n[FASE 1/3] Inicializando base del ZIP maestro clonando teitan_core.zip...")
        t0 = time.time()
        shutil.copyfile(core_zip_path, temp_master_zip)
        print(f"  -> Base transferida en {time.time() - t0:.1f}s.")

        # Paso B: Incorporar AR88 con streaming y SHA-256 en vuelo
        print("\n[FASE 2/3] Incorporando archivos de AR88 por streaming con verificacion de SHA-256 en vuelo...")
        date_substitutions = []
        t_start_ar88 = time.time()
        added_bytes = 0

        zf_active = zipfile.ZipFile(temp_master_zip, 'a', compression=zipfile.ZIP_DEFLATED, allowZip64=True, compresslevel=6)

        for idx, entry in enumerate(ar88_entries, start=1):
            orig_src = entry[1]
            staged_p = entry[2]
            exp_bytes = entry[3]
            expected_sha = entry[4]
            arcname = os.path.splitdrive(orig_src)[1].lstrip('\\/').replace('\\', '/')

            # Validar aislamiento de nuevo en vuelo antes de abrir
            ok_iso, msg_iso = validate_staged_path_isolation(staged_p, allowed_stage_root=stage_root)
            if not ok_iso:
                raise RuntimeError(f"Violacion de aislamiento en vuelo: {msg_iso}")

            st = os.stat(staged_p)
            dt_tuple, subst_reason = get_sanitized_zip_date_time(st.st_mtime)
            if subst_reason:
                date_substitutions.append({
                    "file": arcname,
                    "original_mtime": st.st_mtime,
                    "substituted_date": dt_tuple,
                    "reason": subst_reason
                })

            zinfo = zipfile.ZipInfo(filename=arcname, date_time=dt_tuple)
            zinfo.compress_type = zipfile.ZIP_DEFLATED
            zinfo.external_attr = (st.st_mode & 0xFFFF) << 16

            file_sha = hashlib.sha256()
            read_bytes = 0

            with open(staged_p, "rb") as f_in, zf_active.open(zinfo, "w", force_zip64=(exp_bytes > 2*1024*1024*1024)) as f_out:
                while chunk := f_in.read(4 * 1024 * 1024):
                    file_sha.update(chunk)
                    read_bytes += len(chunk)
                    f_out.write(chunk)

            actual_sha = file_sha.hexdigest().upper()
            if read_bytes != exp_bytes:
                raise RuntimeError(f"ABORTANDO: Tamano leido ({read_bytes}) != Esperado ({exp_bytes}) en {staged_p}")

            if actual_sha != expected_sha:
                raise RuntimeError(f"ABORTANDO: SHA-256 real ({actual_sha}) != Checkpoint ({expected_sha}) en {staged_p}")

            added_bytes += read_bytes
            if idx % 500 == 0 or exp_bytes > 100 * 1024 * 1024:
                el = time.time() - t_start_ar88
                mb_s = (added_bytes / (1024*1024)) / el if el > 0 else 0
                print(f"  AR88 Progreso: {idx}/{len(ar88_entries)} ({added_bytes / (1024**3):.2f} GiB procesados, {mb_s:.1f} MB/s)...")

        zf_active.close()
        zf_active = None
        print(f"  -> Incorporacion y verificacion SHA-256 de AR88 completada en {time.time() - t_start_ar88:.1f}s.")

        # Paso C: Verificacion integral del temporal antes de publicar
        print("\n[FASE 3/3] Verificando integridad fisica final del ZIP temporal...")
        with zipfile.ZipFile(core_zip_path, 'r') as czf:
            core_c = len(czf.namelist())
        expected_total_c = EXPECTED_TOTAL_COUNT if master_zip_path == MASTER_ZIP_PATH else core_c + len(ar88_entries)

        with zipfile.ZipFile(temp_master_zip, 'r') as zf_check:
            final_names = zf_check.namelist()
            total_final = len(final_names)
            unique_final = len(set(final_names))
            if total_final != expected_total_c or unique_final != expected_total_c:
                raise RuntimeError(f"Discrepancia en entradas del ZIP: Total {total_final}, Unicas {unique_final}, Esperadas {expected_total_c}")
            print(f"  -> Conteo verificado: exactamente {total_final} entradas unicas.")

            print("  -> Ejecutando test de integridad CRC completo (testzip)...")
            t_crc = time.time()
            bad_file = zf_check.testzip()
            if bad_file is not None:
                raise RuntimeError(f"Error de CRC en archivo: {bad_file}")
            print(f"  -> Test CRC 100% superado en {time.time() - t_crc:.1f}s.")

        # Paso D: Calculo de SHA-256 definitivo
        print("  -> Calculando hash SHA-256 definitivo del archivo maestro...")
        t_sha = time.time()
        master_sha256 = calculate_sha256(temp_master_zip)
        print(f"  -> SHA-256: {master_sha256} (calculado en {time.time() - t_sha:.1f}s)")

        # Paso E: Publicacion sin sobrescritura atomica (Garantia 3)
        if os.path.exists(master_zip_path):
            raise FileExistsError(f"teitan.zip detectado concurrentemente en {master_zip_path}")

        os.rename(temp_master_zip, master_zip_path)
        final_master_size = os.path.getsize(master_zip_path)
        print(f"\n[OK] teitan.zip publicado exitosamente en: {master_zip_path}")
        print(f"Tamano Real: {final_master_size} bytes ({final_master_size / (1024**3):.2f} GiB)")

        # Paso F: Guardar informe final consolidado con creacion exclusiva atomica (open 'x')
        summary_report = {
            "TIMESTAMP": time.strftime("%Y-%m-%d %H:%M:%S"),
            "STATUS": "BACKUP_COMPLETED_AND_VERIFIED",
            "MASTER_ZIP_PATH": master_zip_path,
            "MASTER_ZIP_BYTES": final_master_size,
            "MASTER_ZIP_GIB": round(final_master_size / (1024**3), 3),
            "MASTER_ZIP_SHA256": master_sha256,
            "TOTAL_FILES_IN_ZIP": total_final,
            "CORE_FILES_COUNT": EXPECTED_CORE_COUNT,
            "AR88_FILES_COUNT": EXPECTED_AR88_COUNT,
            "EXCLUSIONS_PRESENCE_LOCK": 4,
            "DATE_SUBSTITUTIONS_COUNT": len(date_substitutions),
            "DATE_SUBSTITUTIONS": date_substitutions,
            "CRC_INTEGRITY": "PASS",
            "BACKUP_COMPLETED": True
        }

        report_out = final_report_path
        try:
            with open(report_out, "x", encoding="utf-8") as rf:
                json.dump(summary_report, rf, indent=2)
        except FileExistsError:
            # Si existiera concurrentemente, escribir fallback con timestamp unico
            fallback_report = f"{final_report_path}.unique_{int(time.time())}_{uuid.uuid4().hex[:6]}.json"
            print(f"[WARN] {report_out} ya existia. Escribiendo reporte en {fallback_report}")
            with open(fallback_report, "x", encoding="utf-8") as rf:
                json.dump(summary_report, rf, indent=2)
            report_out = fallback_report

        print("\n" + "=" * 68)
        print(f"  INFORME CONSOLIDADO FINAL GENERADO EN: {report_out}")
        print("=" * 68)
        print(json.dumps(summary_report, indent=2))

        build_successful = True
        sys.exit(0)

    except Exception as exc:
        print(f"\n[FALLO CRITICO DURANTE FINALIZACION]: {exc}")
        if zf_active is not None:
            try:
                zf_active.close()
            except Exception:
                pass
            zf_active = None

        if not build_successful and os.path.exists(temp_master_zip):
            print(f"[LIMPIEZA DE SEGURIDAD] Eliminando archivo temporal fallido: {temp_master_zip}")
            try:
                os.remove(temp_master_zip)
                print("[LIMPIEZA DE SEGURIDAD] Archivo temporal eliminado correctamente.")
            except Exception as e_del:
                print(f"[ALERTA] No se pudo eliminar el temporal: {temp_master_zip} -> {e_del}")

        sys.exit(1)

    finally:
        if zf_active is not None:
            try:
                zf_active.close()
            except Exception:
                pass

if __name__ == "__main__":
    if len(sys.argv) > 1 and sys.argv[1] == "--preflight":
        ok = run_preflight()
        sys.exit(0 if ok else 1)
    elif len(sys.argv) > 1 and sys.argv[1] == "--finalize":
        run_finalize()
    else:
        print("Uso:")
        print("  python finalize_master_v521.py --preflight")
        print("  python finalize_master_v521.py --finalize")
        sys.exit(1)

