# ============================================================
# 09 — Tracer-MED: a hospital audit trail that survives outside the system
#
# Colab:  !pip install winnex-madhava winnex-tracer
# ============================================================

# instalação automática — Colab, Jupyter e script local.
# No Colab, "!pip" dentro de comentário não executa: a instalação
# precisa acontecer de dentro da célula, antes dos imports.
import importlib
import subprocess
import sys

for _pkg in ["winnex-madhava", "winnex-tracer"]:
    _mod = _pkg.replace("-", "_")
    try:
        __import__(_mod)
        continue
    except ImportError:
        pass
    _r = subprocess.run(
        [sys.executable, "-m", "pip", "install", "-q", "--upgrade", _pkg],
        capture_output=True, text=True
    )
    # O interpretador do Colab já está em execução quando o pip termina.
    # Sem invalidar o cache, o import abaixo pode não enxergar o pacote.
    importlib.invalidate_caches()
    try:
        __import__(_mod)
    except ImportError:
        sys.stderr.write(_r.stdout or "")
        sys.stderr.write(_r.stderr or "")
        raise SystemExit(
            "\n\nNão foi possível importar " + _pkg + " após instalar.\n"
            "No Colab: menu 'Ambiente de execução' -> 'Reiniciar sessão',\n"
            "e execute esta célula novamente.\n"
        )

import numpy as np
import winnex_madhava as mad
from winnex_tracer.core import InstrumentedEngine

DIM = 128

def embed(t):
    v = np.zeros(DIM, dtype=np.float32)
    for tok in t.lower().split():
        for i, ch in enumerate(tok):
            v[(ord(ch) * 31 + i * 7) % DIM] += 1.0
    n = np.linalg.norm(v)
    return v / n if n else v

# 1. um serviço de auditoria médica tem centenas de laudos.
#    Usamos 400 laudos sintéticos aqui para que o bound tenha corpus
#    sobre o qual atuar — com 4 documentos um top-k de 2 exclui apenas 2.

import random
random.seed(42)
achados = [
    "apendicite aguda confirmada por tomografia com indicação cirúrgica",
    "cólica renal com hidronefrose leve sem obstrução",
    "inconclusivo para apendicite, sugerida reavaliação em 12 horas",
    "sem alterações significativas, alta com analgesia simples",
    "colecistite aguda com espessamento parietal ao ultrassom",
    "pancreatite leve sem coleção peripancreática",
    "diverticulite não complicada em cólon sigmoide",
    "pneumonia lobar à direita com consolidação",
    "insuficiência cardíaca descompensada com congestão pulmonar",
    "tromboembolismo pulmonar excluído por angiotomografia",
]
laudos = []
for i in range(400):
    base_txt = random.choice(achados)
    laudos.append(f"LAU-{i+1:04d} {base_txt}")

corpus = np.stack([embed(l) for l in laudos]).astype(np.float32)

# 2. instrumenta o engine — toda busca gera registro assinado
base = mad.build_engine(corpus, dim=DIM, k=2, k1_fraction=1.0,
                        postfilter=True, audit_exhaustive=True)
engine = InstrumentedEngine(base, mode="commitment")

# 3. busca de auditoria
r = engine.search_with_commitment(embed("apendicite"), k=2)

print(f"laudos no corpus    : {len(laudos)}")
print(f"laudos encontrados  : {len(r['indices'])}")
print(f"excluídos com prova : {r['total_excluded_count']}")
print(f"threshold global    : {r['global_threshold']:.4f}")
print(f"garantia            : {r['recall_guarantee']}")
print(f"bound violations    : {r['bound_violations']}")

print("\nregistro de exclusão (amostra):")
for rec in r["sampled_records"][:3]:
    print(f"  doc {rec['doc_id']}: bound={rec['upper_bound']:.4f} excluído={rec['excluded']}")

assert r["bound_violations"] == 0
assert r["recall_guarantee"] == "exact_global"
print("\nOK — busca com garantia global e trilha de auditoria registrada.")
