#!/usr/bin/env python3
"""Regression tests fuer aria-akp-triage.py Junk-Penalty-Guard (KAR-685).

Belegt: Junk-Content wird messbar runtergescored (Brain-Rot-Guard,
Xing et al. 2025 / arXiv:2510.13928).

Run: python3 /root/aria/scripts/tests/test_triage_junk_penalty.py
Modul hat Bindestriche -> Load via importlib.
"""
import importlib.util
import sqlite3
import sys
import tempfile
from pathlib import Path

SCRIPT = Path("/root/aria/scripts/aria-akp-triage.py")
spec = importlib.util.spec_from_file_location("akptriage", SCRIPT)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)

# Live-Config-Thresholds (brain/youtube/.config.yaml): 2.0 / 2 / 1.5
PROMOTE_AVG, PROMOTE_ARIA, SUMMARY_AVG = 2.0, 2, 1.5
cv = lambda s, jp: mod.compute_verdict(s, jp, PROMOTE_AVG, PROMOTE_ARIA, SUMMARY_AVG)

PASS = "\033[32mPASS\033[0m"
FAIL = "\033[31mFAIL\033[0m"
results = []


def check(name, cond):
    results.append(bool(cond))
    print(f"  [{PASS if cond else FAIL}] {name}")


HIGH = {"depth": 3, "novelty": 3, "aria_relevance": 3, "production_ready": 3}
MID = {"depth": 2, "novelty": 2, "aria_relevance": 2, "production_ready": 2}
RELEVANCE_ONLY = {"depth": 0, "novelty": 0, "aria_relevance": 3, "production_ready": 0}

print("== compute_verdict ==")
# A: top quality, kein Junk -> promote
v, avg, eff = cv(HIGH, 0)
check("A clean top-quality -> promote", v == "promote" and eff == 3.0)

# B: top quality ABER junk_penalty=2 -> promote blockiert -> summary_only
vB, _, effB = cv(HIGH, 2)
check("B jp=2 blockt promote trotz Top-Score -> summary_only", vB == "summary_only")

# C: top quality ABER junk_penalty=3 -> hard skip (reiner Junk wird gekillt)
vC, _, _ = cv(HIGH, 3)
check("C jp=3 erzwingt skip trotz Top-Score", vC == "skip")

# D: borderline promote (mid) ohne Junk -> promote; mit jp=1 -> demote auf summary_only
vD0, _, _ = cv(MID, 0)
vD1, _, effD1 = cv(MID, 1)
check("D mid jp=0 -> promote", vD0 == "promote")
check("D mid jp=1 demote -> summary_only (eff 2.0->1.5)", vD1 == "summary_only" and effD1 == 1.5)

# E: High-Relevance-Sneak-Path (OR-Klausel) wird durch Junk geschlossen
vE0, _, _ = cv(RELEVANCE_ONLY, 0)
vE2, _, effE2 = cv(RELEVANCE_ONLY, 2)
check("E relevance-only jp=0 -> summary_only (OR-Pfad)", vE0 == "summary_only")
check("E relevance-only jp=2 -> skip (Sneak-Path geschlossen)", vE2 == "skip")

# F: avg_positive bleibt von Penalty unberuehrt (Transparenz), nur eff sinkt
_, avgF, effF = cv(MID, 2)
check("F avg_positive unveraendert (2.0), eff gesenkt (1.0)", avgF == 2.0 and effF == 1.0)

# Monotonie: mehr Junk -> nie besseres Verdict
order = {"skip": 0, "summary_only": 1, "promote": 2}
ranks = [order[cv(HIGH, jp)[0]] for jp in (0, 1, 2, 3)]
check("G Monotonie: Verdict faellt monoton mit junk_penalty", ranks == sorted(ranks, reverse=True))

print("== ensure_schema (Migration) ==")
fd, dbp = tempfile.mkstemp(suffix=".sqlite")
Path(dbp).unlink()
con = sqlite3.connect(dbp)
con.execute("""CREATE TABLE triaged (video_id TEXT PRIMARY KEY, depth INTEGER,
    novelty INTEGER, aria_relevance INTEGER, production_ready INTEGER, avg_score REAL,
    verdict TEXT, one_line_reason TEXT, triage_path TEXT, cost_usd REAL)""")
con.commit()
cols_before = {r[1] for r in con.execute("PRAGMA table_info(triaged)")}
mod.ensure_schema(con)
cols_after = {r[1] for r in con.execute("PRAGMA table_info(triaged)")}
check("H junk_penalty fehlt vorher, da nachher", "junk_penalty" not in cols_before and "junk_penalty" in cols_after)
# Idempotenz: zweiter Lauf darf nicht crashen
try:
    mod.ensure_schema(con)
    check("I ensure_schema idempotent (kein Crash)", True)
except Exception as e:  # noqa
    check(f"I ensure_schema idempotent (kein Crash): {e}", False)

# store_triage Roundtrip schreibt junk_penalty
con.row_factory = sqlite3.Row
mod.store_triage(con, "vid1", MID, "summary_only", "test", "/tmp/x.json", 0.001, junk_penalty=2)
row = con.execute("SELECT junk_penalty, avg_score, verdict FROM triaged WHERE video_id='vid1'").fetchone()
check("J store_triage persistiert junk_penalty=2", row["junk_penalty"] == 2 and row["verdict"] == "summary_only")
con.close()
Path(dbp).unlink()

print()
if all(results):
    print(f"All {len(results)} checks {PASS}")
    sys.exit(0)
print(f"{results.count(False)}/{len(results)} checks {FAIL}")
sys.exit(1)
