"""PostHog-loop playbook, step 10: the incrementality readout of the holdout.

Every delivery cycle under the experiment recorded which users it delivered
to (the treated group) and which it withheld (the holdout). The readout
compares the label's outcome rates of the two groups over a window: the
difference and a bootstrap 95% interval.

An outcome counts when it matures one label horizon (7 days) after the
delivery that anchored the user; on the local stack the delivery ran eight days
ago (step 9). This fixture has no real users who could react, so the step
uploads a generated follow-up outcome for every user, observed now and drawn
from one seeded coin that ignores the group: the readout shows the computation
and should find no effect, and the page says so.
"""

import csv
import hashlib
import io
import sys
from datetime import UTC, datetime, timedelta
from pathlib import Path

import httpx

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

api, state = Api(), State("posthog-loop")

deliveries = api.get(f"/destinations/{state['destination_id']}/deliveries").get("data") or []
first_delivery = min(
    datetime.fromisoformat(str(item["created_at"]).replace("Z", "+00:00")) for item in deliveries
)
window_start = first_delivery - timedelta(hours=1)
users = sorted(
    row["entity_id"]
    for row in csv.DictReader(
        (Path(state["sample_dir"]) / "labels_repeat_purchase.csv").read_text().splitlines()
    )
)
outcome_at = (datetime.now(UTC) - timedelta(minutes=1)).strftime("%Y-%m-%dT%H:%M:%S.%fZ")
table = io.StringIO()
writer = csv.writer(table)
writer.writerow(["entity_id", "value", "observed_at"])
for user in sorted(set(users)):
    # One seeded coin per user, blind to the experiment: no planted effect.
    draw = int(hashlib.sha256(f"follow-up:{user}".encode()).hexdigest()[:8], 16) / 0xFFFFFFFF
    writer.writerow([user, "true" if draw < 0.3 else "false", outcome_at])
session = api.post(
    "/uploads",
    {
        "filename": "followup_outcomes.csv",
        "format": "csv",
        "source_id": state["label_source_id"],
    },
    key="posthog-loop-followup-upload",
)
httpx.put(
    session["upload_url"], content=table.getvalue().encode(), timeout=120.0
).raise_for_status()
api.post(f"/uploads/{session['upload_id']}:complete")
upload = api.get(f"/uploads/{session['upload_id']}")
sync = api.wait(
    f"/syncs/{upload['sync_id']}",
    lambda item: item.get("status") in ("succeeded", "failed"),
    what="the follow-up outcome sync",
    polls=150,
)
print(f"follow-up outcomes: {sync['status']}")
window_end = datetime.now(UTC)  # after the outcomes were observed
readout = api.get(
    f"/slots/growth/experiments/{state['experiment_id']}/readout",
    label_id=state["label_id"],
    start=window_start.strftime("%Y-%m-%dT%H:%M:%SZ"),
    end=window_end.strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
)
treated, holdout = readout["treated"], readout["holdout"]
print(f"treated users with an outcome: {treated['n']}, rate {treated['rate']:.3f}")
print(f"held-out users with an outcome: {holdout['n']}, rate {holdout['rate']:.3f}")
print(f"difference: {readout['delta']:+.3f}, 95% interval {readout['ci95']}")
low, high = readout["ci95"]
print(f"readout computed: {treated['n'] >= 30 and holdout['n'] >= 30}")
print(f"no planted effect found (the interval covers zero): {low <= 0.0 <= high}")
