"""The two arms, their intervals and the verdicts. Step 5 of five, and last.

    python research/red-sky/analyse.py [--distance 300]

Run `controls.py` first and read what it printed. This file computes the real
statistic, which is the one number the whole order of work exists to keep until
the end.

It prints, for each arm: the primary (stratified by site x calendar month), the
crude pooled difference beside it and never instead, the two halves of the
construct on their own, the exposure counts, and the verdict from `rule.py`'s
kill rule. Nothing in it decides anything the rule did not already decide.
"""
import os
import sys

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import stats as S  # noqa: E402

OUT = os.path.expanduser("~/data/red-sky")
BAR = 5.0


def crude(rows, label_key, outcome_key):
    """One stratum: the pooled difference, for the row beside the primary."""
    flat = [dict(r, site="_", month=0) for r in rows]
    n1, s1, n0, s0, st, ns = S.blocks(flat, label_key, outcome_key)
    return S.delta(n1, s1, n0, s0, st, ns)


def arm(rows, name, label_key, outcome_key, direction):
    packed = S.blocks(rows, label_key, outcome_key)
    n1, s1, n0, s0, stratum_of, n_strata = packed
    exposed, unexposed = int(n1.sum()), int(n0.sum())
    point, lo, hi = S.interval(packed)
    print(f"{name}")
    print(f"    exposed {exposed}, unexposed {unexposed}, "
          f"{n_strata} strata, {len(n1)} blocks")
    if exposed < 500:
        print("    VOID for want of exposure: fewer than 500 exposed site-days.")
    print(f"    P(outcome | label)     {100 * s1.sum() / max(n1.sum(), 1):.2f} %")
    print(f"    P(outcome | not label) {100 * s0.sum() / max(n0.sum(), 1):.2f} %")
    print(f"    stratified delta  {point:+.3f} points, 95 % "
          f"[{lo:+.3f}, {hi:+.3f}]   <- primary")
    print(f"    crude delta       {crude(rows, label_key, outcome_key):+.3f} points")
    if direction:
        v = S.verdict(lo, hi, BAR, direction)
        side = "+" if direction > 0 else "-"
        print(f"    against a bar of {side}{BAR:.0f} points: {v}")
        if v == "KILLED" and ((direction > 0 and lo > 0) or (direction < 0 and hi < 0)):
            print("    and the interval excludes zero on the proverb's own side: "
                  "the saying points the right way and is too weak to use.")
    print()
    return point, lo, hi


def main():
    km = 300
    if "--distance" in sys.argv:
        km = int(sys.argv[sys.argv.index("--distance") + 1])
    rows = S.read_rows(os.path.join(OUT, f"site-days-{km}.csv"))
    sites = sorted({r["site"] for r in rows})
    print(f"{len(rows)} usable site-days, {len(sites)} sites, "
          f"upwind point at {km} km\n")

    arm(rows, "NIGHT ARM: red sky at night -> fine tomorrow",
        "red_night", "fine_next", +1)
    arm(rows, "  half: CLEAR_WEST alone (no cloud-overhead requirement)",
        "clear_w", "fine_next", 0)
    arm(rows, "  half: LIT_SKY alone (cloud overhead, upwind ignored)",
        "lit", "fine_next", 0)
    arm(rows, "MORNING ARM: red sky in the morning -> wet today",
        "red_morning", "fine_today", -1)

    arm(rows, "  half: CLEAR_EAST alone at sunrise (upwind ignored)",
        "clear_e", "fine_today", 0)
    arm(rows, "  half: LIT_SKY at sunrise alone (cloud overhead at dawn)",
        "lit_rise", "fine_today", 0)

    print("The difference between the night arm and CLEAR_WEST is what the word "
          "'red' is buying. Read it before the verdict.")
    print("Robustness: run load.py and this file at --distance 150 and 450.")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
