"""malin_doctor.py - ONE read-only diagnostic for Malin's hanging render.

Run:  C:\\ComfyUI\\.venv\\Scripts\\python.exe C:\\malin\\malin_doctor.py

Makes NO changes. It tests the ONE hypothesis (insightface/onnxruntime knocked off the
GPU) directly, then shows ComfyUI's own log of where the last render got stuck.
Every step prints BEFORE it runs and flushes, so if the output STOPS at a step, that
step is the hang. Paste the WHOLE output back once.
"""
import os, sys, glob, time, traceback

def step(msg):
    print(f"\n=== {msg} ===", flush=True)

# ---------------------------------------------------------------- 1. versions
step("1. PACKAGE VERSIONS")
for pkg in ["torch", "numpy", "onnxruntime", "insightface"]:
    try:
        m = __import__(pkg)
        print(f"{pkg}: {getattr(m, '__version__', '?')}", flush=True)
    except Exception as e:
        print(f"{pkg}: NOT IMPORTABLE ({e})", flush=True)
try:
    import cv2
    print(f"cv2: {cv2.__version__}", flush=True)
except Exception as e:
    print(f"cv2: NOT IMPORTABLE ({e})", flush=True)

# ---------------------------------------------------------------- 2. torch CUDA
step("2. TORCH CUDA")
try:
    import torch
    ok = torch.cuda.is_available()
    print("torch.cuda.is_available:", ok, flush=True)
    print("device:", torch.cuda.get_device_name(0) if ok else "NONE", flush=True)
except Exception as e:
    print("torch cuda check failed:", e, flush=True)

# ---------------------------------------------------------------- 3. onnxruntime providers
step("3. ONNXRUNTIME PROVIDERS  (the prime suspect)")
try:
    import onnxruntime as ort
    provs = ort.get_available_providers()
    print("available providers:", provs, flush=True)
    print("CUDAExecutionProvider present:", "CUDAExecutionProvider" in provs, flush=True)
except Exception as e:
    print("onnxruntime check failed:", e, flush=True)
    traceback.print_exc()

# ---------------------------------------------------------------- 4. insightface inference, TIMED
step("4. INSIGHTFACE INFERENCE  (if output STOPS here, THIS is the hang)")
try:
    import cv2
    from insightface.app import FaceAnalysis
    print("creating FaceAnalysis(buffalo_l)...", flush=True)
    app = FaceAnalysis(name="buffalo_l",
                       providers=["CUDAExecutionProvider", "CPUExecutionProvider"])
    print("prepare(ctx_id=0)...", flush=True)
    app.prepare(ctx_id=0, det_size=(640, 640))
    try:
        rec = app.models.get("recognition")
        if rec is not None:
            print("recognition model actually using:", rec.session.get_providers(), flush=True)
    except Exception:
        pass
    # find any face image to time inference on
    pool = sorted(glob.glob(r"C:\ComfyUI\input\*.png")) + sorted(glob.glob(r"C:\ComfyUI\input\*.jpg"))
    img_path = pool[0] if pool else None
    print("test image:", img_path, flush=True)
    if img_path:
        img = cv2.imread(img_path)
        print("running app.get() ...", flush=True)
        t0 = time.time()
        faces = app.get(img)
        print(f"RESULT: {len(faces)} face(s) in {time.time() - t0:.2f}s", flush=True)
    else:
        print("no image in C:\\ComfyUI\\input to test on", flush=True)
except Exception as e:
    print("insightface inference FAILED:", e, flush=True)
    traceback.print_exc()

# ---------------------------------------------------------------- 5. ComfyUI log tail
step("5. COMFYUI LOG TAIL  (server's view of the last render - trigger one selfie FIRST)")
globs = [
    os.path.expandvars(r"%APPDATA%\ComfyUI\logs\*.log"),
    os.path.expandvars(r"%APPDATA%\ComfyUI\*.log"),
    os.path.expandvars(r"%APPDATA%\ComfyUI\**\*.log"),
    r"C:\ComfyUI\user\comfyui*.log",
    r"C:\ComfyUI\comfyui*.log",
    r"C:\ComfyUI\**\*.log",
]
found = []
for g in globs:
    try:
        found += glob.glob(g, recursive=True)
    except Exception:
        pass
found = [f for f in set(found) if os.path.isfile(f)]
if not found:
    print("no ComfyUI log file found (steps 1-4 are still decisive)", flush=True)
else:
    newest = max(found, key=os.path.getmtime)
    print("newest log:", newest, flush=True)
    try:
        with open(newest, "r", encoding="utf-8", errors="replace") as f:
            lines = f.readlines()
        print("--- last 90 lines ---", flush=True)
        sys.stdout.write("".join(lines[-90:]))
        sys.stdout.flush()
    except Exception as e:
        print("could not read log:", e, flush=True)

print("\n=== DONE. Paste everything above. ===", flush=True)
