"""Security-lake playbook, step 9: an alert rule, a scored book, a disposition.

The rule opens an episode when a user's behavior is more surprising than 95%
of their peers (`behavior_surprise`, a calibrated percentile). A batch refresh
scores every user as of the end of the lake window; the alerted user's served
state carries the evidence that moved the score. The analyst's disposition
(here taken from the fixture's ground truth) feeds the rule's precision rollup.
"""

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))  # playbooks/playbook_api.py
from playbook_api import Api, State

api, state = Api(), State("security-lake")

rule = api.post(
    "/slots/security/alert-rules",
    {
        "name": "behavior more surprising than 95% of peers",
        "predicate": {"select": {"kind": "behavior_surprise"}, "op": "gte", "value": 0.95},
    },
    key="security-lake-rule",
)
print(f"alert rule: {rule['status']}")
refresh = api.post(
    "/slots/security/refreshes", {"cutoff": state["cutoff"]}, key="security-lake-refresh"
)
refresh = api.wait(
    f"/slots/security/refreshes/{refresh['refresh_id']}",
    lambda item: item.get("status") in ("succeeded", "failed"),
    what="the batch refresh",
)
print(f"refresh: {refresh['status']}, users scored: {refresh.get('entities_scored')}")

episodes = api.get("/slots/security/alert-episodes", rule_id=rule["rule_id"]).get("data") or []
print(f"episodes opened: {len(episodes) > 0}")
if not episodes:
    sample = [
        api.get(f"/slots/security/entities/user/{user}/state") for user in state["takeovers"][:10]
    ]
    seen = [
        ((row.get("signals") or {}).get("behavior_surprise"), row.get("scores")) for row in sample
    ]
    sys.exit(f"no user crossed the surprise threshold; takeover users' state: {seen}")
takeovers = set(state["takeovers"])
episode = sorted(episodes, key=lambda item: item["entity_id"] not in takeovers)[0]
user = episode["entity_id"]
served = api.get(f"/slots/security/entities/user/{user}/state")
evidence = ((served.get("signals") or {}).get("evidence") or {}).get("transitions") or []
print(f"evidence on the alerted user: {len(evidence) > 0}")
verdict = "true_positive" if user in takeovers else "false_positive"
judged = api.post(
    f"/slots/security/alert-episodes/{episode['episode_id']}:disposition",
    {"disposition": verdict, "reason": "fixture ground truth"},
)
print(f"disposition recorded: {judged['disposition']['disposition'] == verdict}")
rollup = (
    api.get("/slots/security/monitors/alert-precision", rule_id=rule["rule_id"]).get("data") or [{}]
)[0]
print(f"precision rollup dispositioned: {rollup.get('dispositioned')}")
state.update(rule_id=rule["rule_id"])
