﻿import sys
import os
import json
import inspect
from pathlib import Path

root = Path(sys.argv[1]).resolve()
client_dir = root / "artifacts" / "distribution" / "client_alpha_src"
config_path = Path(sys.argv[2]).resolve()
lab = Path(sys.argv[3]).resolve()

data = json.loads(config_path.read_text(encoding="utf-8-sig"))

if data.get("authorized_role") != "CREATOR":
    raise RuntimeError("ROL_CREATOR_NO_CONFIRMADO")

if not data.get("device_id"):
    raise RuntimeError("DEVICE_ID_ORIGINAL_NO_ENCONTRADO")

print("ARCLIENT_IDENTIDAD_ORIGINAL=PASS", flush=True)

# Preparar exclusivamente campos no secretos.
safe_config = {
    "authorized_role": data["authorized_role"],
    "device_id": data["device_id"],
    "active_conversation_id": data.get("active_conversation_id"),
    "server_url": None,
    "pinned_fingerprint": None,
    "token": None,
}

# Bloquear operaciones de red, subprocess y escrituras
# externas al laboratorio mediante el mecanismo de auditoría Python.
# No es aislamiento absoluto de código nativo.
def within_lab(value):
    try:
        p = Path(value).resolve()
        return p == lab or lab in p.parents
    except Exception:
        return False

def audit(event, args):
    if event in (
        "socket.connect", "socket.connect_ex",
        "socket.bind", "subprocess.Popen",
        "os.system", "os.startfile"
    ):
        print("ARCLIENT_OPERACION_BLOQUEADA=" + event, flush=True)
        raise PermissionError("OPERACION_BLOQUEADA")

    if event == "open" and args:
        mode = args[1] if len(args) > 1 else "r"
        flags = args[2] if len(args) > 2 else 0
        writing = isinstance(mode, str) and any(c in mode for c in "wax+")
        if isinstance(flags, int):
            writing |= bool(flags & (
                os.O_WRONLY | os.O_RDWR | os.O_CREAT |
                os.O_TRUNC | os.O_APPEND
            ))
        if writing and not within_lab(args[0]):
            print("ARCLIENT_ESCRITURA_BLOQUEADA", flush=True)
            raise PermissionError("ESCRITURA_EXTERNA_BLOQUEADA")

    if event in ("os.mkdir", "os.remove", "os.rmdir",
                 "os.rename", "os.replace", "os.unlink"):
        paths = args[:2] if event in ("os.rename","os.replace") else args[:1]
        if not all(within_lab(p) for p in paths):
            print("ARCLIENT_MUTACION_BLOQUEADA", flush=True)
            raise PermissionError("MUTACION_EXTERNA_BLOQUEADA")

sys.addaudithook(audit)

sys.path.insert(0, str(root))
sys.path.insert(0, str(client_dir))

import client

wb_class = getattr(client, "CreatorWorkbench", None)

if wb_class is None:
    raise RuntimeError("CREATOR_WORKBENCH_NO_IMPORTADO")

real_wb = Path(inspect.getfile(wb_class)).resolve()
expected_wb = (client_dir / "workbench.py").resolve()

if real_wb != expected_wb:
    raise RuntimeError("WORKBENCH_NO_PROVIENE_DE_KINGSTON")

print("ARCLIENT_WORKBENCH_SOURCE=PASS", flush=True)
print("ARCLIENT_WORKBENCH_PATH=" + str(real_wb), flush=True)

# Neutralizar solamente en esta prueba:
# configuración, emparejamiento y asistente de primera conexión.
klass = client.DigitalOptimusClient

for method in ("save_config","pair_device","first_run_config"):
    if not hasattr(klass, method):
        raise RuntimeError("METODO_NO_LOCALIZADO_" + method)

klass.save_config = lambda self: None
klass.pair_device = lambda self: None
klass.first_run_config = lambda self: None

app = klass(config=safe_config)

print("ARCLIENT_GUI_CREATED=SI", flush=True)
print("ARCLIENT_ROLE=" + str(app.authorized_role), flush=True)

# Cierre automático de la prueba.
app.after(12000, app.destroy)
app.mainloop()

print("ARCLIENT_GUI_EXITED=SI", flush=True)
print("ARCLIENT_BRAIN_SOLICITADO=NO", flush=True)
print("ARCLIENT_DEVELOPER_SOLICITADO=NO", flush=True)
