"""Every figure in "The IRS Handed Back 96.7% of the Money on Its AI Coding-Tools Order", recomputed from the saved
USAspending API responses and asserted.

Inputs (beside this script, in data/): the three collection scripts' saved output
  data/ai_fy26.json            POST /api/v2/search/spending_by_transaction/ — keyword "artificial intelligence", award types
                               A-D, 2025-10-01 .. 2026-09-17; pulled 2026-09-18T00:43:05Z (449 rows)
  data/ai_fy26_verdicts.json   the 34 negative lines, each classified against its own award's modification history
                               (POST /api/v2/transactions/): OFFSET / STANDING / TERMINATION / CLOSEOUT
  data/awards.out.txt          GET /api/v2/awards/<id>/ — the named awards' own records (obligated, ceiling, period, text)

The script reloads the rows, recomputes the census totals, the four bins and every derived number the essay quotes, and
asserts each quoted amount, date and record line is present in the rows. A figure that drifts from its source fails the run.

Run: python figures_c6153.py            (reads data/ next to it; no network)
"""
import json
import re
import sys
from pathlib import Path

HERE = Path(__file__).resolve().parent
DATA = HERE / "data"
FAILS = []


def check(cond, label):
    print(("  ok   " if cond else "  FAIL ") + label)
    if not cond:
        FAILS.append(label)


def money(x):
    return "$%s" % format(round(x, 2), ",.2f")


census = json.load(open(DATA / "ai_fy26.json", encoding="utf-8"))
rows = census if isinstance(census, list) else next(v for v in census.values() if isinstance(v, list) and len(v) > 100)
ver = json.load(open(DATA / "ai_fy26_verdicts.json", encoding="utf-8"))
neg = ver["rows"]
amt = lambda r: float(r["Transaction Amount"])

print("== the census")
pos_total = sum(amt(r) for r in rows if amt(r) > 0)
neg_rows = [r for r in rows if amt(r) < 0]
neg_total = sum(amt(r) for r in neg_rows)
check(len(rows) == 449, "449 transactions in the FY2026 pull")
check(round(pos_total, 2) == 358899346.16, "$358,899,346.16 obligated (sum of positive lines) -> %s" % money(pos_total))
check(round(neg_total, 2) == -14990819.87 and len(neg_rows) == 34,
      "$14,990,819.87 de-obligated across 34 negative lines -> %s / %d" % (money(-neg_total), len(neg_rows)))
check(ver["offset_window_days"] == 30, "offset window is 30 days")
types = {}
for r in rows:
    types.setdefault(r.get("Action Type") or "", []).append(amt(r))
unresolved = [k for k in ("W", "H", "L") if k in types]
check(sum(len(types[k]) for k in unresolved) == 7 and all(v >= 0 for k in unresolved for v in types[k]),
      "7 rows carry W/H/L codes and none is negative")
descs = ver["action_type_descriptions"]
check(descs.get("F", "").upper().startswith("TERMINATE FOR CONVENIENCE"), "F = terminate for convenience (from the API row)")
check(descs.get("K", "").upper() == "CLOSE OUT", "K = close out (from the API row)")
check(descs.get("C", "").upper() == "FUNDING ONLY ACTION", "C = funding only action (from the API row)")
check(descs.get("B", "").upper().startswith("SUPPLEMENTAL AGREEMENT"), "B = supplemental agreement for work within scope (from the API row)")

print("== the four bins")
bins = {}
for r in neg:
    bins.setdefault(r["verdict"], []).append(r)
tot = lambda k: round(sum(amt(r) for r in bins.get(k, [])), 2)
check(len(bins.get("OFFSET", [])) == 2 and tot("OFFSET") == -8162903.45, "OFFSET: 2 lines, $8,162,903.45 -> %s" % money(-tot("OFFSET")))
check(len(bins.get("CLOSEOUT", [])) == 5 and tot("CLOSEOUT") == -230099.96, "CLOSEOUT: 5 lines, $230,099.96 -> %s" % money(-tot("CLOSEOUT")))
check(len(bins.get("TERMINATION", [])) == 3 and tot("TERMINATION") == -1926136.26, "TERMINATION: 3 lines, $1,926,136.26 -> %s" % money(-tot("TERMINATION")))
check(len(bins.get("STANDING", [])) == 24 and tot("STANDING") == -4671680.20, "STANDING: 24 lines, $4,671,680.20 -> %s" % money(-tot("STANDING")))
check(round(sum(tot(k) for k in bins), 2) == -14990819.87, "the four bins sum to the census's de-obligated total")

print("== the IRS order, 2032L225F00049")
irs = [r for r in neg if r["Award ID"] == "2032L225F00049"]
check(len(irs) == 1 and amt(irs[0]) == -3205416.90 and irs[0]["Action Date"] == "2026-07-09" and irs[0]["Mod"] == "P00001"
      and irs[0]["Action Type"] == "C" and irs[0]["verdict"] == "STANDING",
      "one negative line: -$3,205,416.90 on 2026-07-09, mod P00001, code C, verdict STANDING")
irs_text = re.sub(r"\s+", " ", irs[0]["Transaction Description"]).strip()
check(irs_text == "THIS IS A REQ FOR MOD TO DE-OBLIGATE FUNDING FOR ARTIFICIAL INTELLIGENCE CODING TOOLS AND ARTIFICIAL INTELLIGENCE CHAT TOOLS AGAINST 2032L225D00002.",
      "the modification's text, quoted verbatim (whitespace collapsed)")
awards = open(DATA / "awards.out.txt", encoding="utf-8").read()
blk = awards[awards.index("2032L225F00049"):]
blk = blk[:blk.index("\n==") if "\n==" in blk else None]
m = re.search(r"obligated ([\d.]+) \| base\+exercised ([\d.]+) \| base\+all options ([\d.]+)", blk)
left, ceiling = float(m.group(1)), float(m.group(3))
check(left == 108975.10 and ceiling == 5080563.10, "left on the order $108,975.10; ceiling $5,080,563.10 -> %s / %s" % (money(left), money(ceiling)))
obligated = round(left + 3205416.90, 2)
check(obligated == 3314392.00, "original obligation $3,314,392.00 = left + de-obligated -> %s" % money(obligated))
check(round(100 * 3205416.90 / obligated, 1) == 96.7 and round(100 * left / obligated, 1) == 3.3, "96.7% returned, 3.3% kept")
check("2025-09-30 .. 2026-09-29" in blk, "period of performance 2025-09-30 .. 2026-09-29")
check("DELIVERY ORDER 1 FOR ARTIFICIAL INTELLIGENCE CODING TOOLS AND ARTIFICIAL INTELLIGENCE CHAT TOOLS AGAINST 2032L225D00002" in blk, "the award's own text, quoted")
check("PERPETUAL LICENSE SOFTWARE" in blk.upper(), "PSC: perpetual license software")
check(round(100 * 3205416.90 / -tot("STANDING"), 1) == 68.6, "the IRS line is 68.6% of the STANDING bin")
others = [r for r in bins["STANDING"] if r["Award ID"] != "2032L225F00049"]
check(len(others) == 23 and round(sum(amt(r) for r in others), 2) == -1466263.30 and min(amt(r) for r in others) == -394959.23,
      "the other 23 standing lines sum to $1,466,263.30; the largest is $394,959.23")
treasury = [r for r in rows if r.get("Awarding Agency") == "Department of the Treasury"]
check(any(amt(r) == 1734979.00 and r["Action Date"] == "2026-09-09" and "MITRE" in r["Recipient Name"].upper() for r in treasury),
      "Treasury: MITRE $1,734,979.00 on 2026-09-09")
check(any(amt(r) == 485864.89 and r["Action Date"] == "2026-08-29" and "UNISON" in r["Recipient Name"].upper() for r in treasury),
      "Treasury: Unison $485,864.89 on 2026-08-29")

print("== the ECS offset pair, W911QX25C0002")
ecs = sorted([r for r in rows if r["Award ID"] == "W911QX25C0002"], key=lambda r: r["Action Date"])
by = {(r["Action Date"], amt(r)) for r in ecs}
check(("2026-05-29", -7812903.45) in by and ("2026-06-03", 7812903.45) in by, "-$7,812,903.45 on 2026-05-29 and +$7,812,903.45 on 2026-06-03")
check(min(amt(r) for r in neg) == -7812903.45, "the largest negative line of the year")
check(round(100 * 7812903.45 / 14990819.87, 1) == 52.1, "52.1% of the year's de-obligated total")
for d, v in (("2026-01-30", 6737560.46), ("2026-02-26", 4475886.00), ("2026-03-30", 10028288.07), ("2026-05-13", 4941047.00)):
    check((d, v) in by, "ECS grew: +%s on %s" % (money(v), d))
eblk = awards[awards.index("W911QX25C0002"):]; eblk = eblk[:eblk.index("\n==")]
check("obligated 72819404.2 " in eblk and "base+all options 97637874.98" in eblk, "ECS obligated $72,819,404.20 of a $97,637,874.98 ceiling")

print("== the three terminations")
term = {r["Award ID"]: r for r in bins["TERMINATION"]}
sec = term["50310225F0034"]
check(amt(sec) == -851509.27 and sec["Action Date"] == "2025-12-08" and sec["Action Type"] == "F", "SEC: -$851,509.27 on 2025-12-08, code F")
check("TERMINATED ALL REMAINING AIML WORK BEYOND THE TERMINATION OF CONVENIENCE NOTICE, TO INCLUDE ALL OPTIONAL OUTYEARS" in sec["Transaction Description"], "SEC: the termination line, quoted")
sblk = awards[awards.index("50310225F0034"):]; sblk = sblk[:sblk.index("\n==")]
check("obligated 482231.26 " in sblk, "SEC: $482,231.26 left")
check(round(482231.26 + 851509.27, 2) == 1333740.53 and round(100 * 482231.26 / 1333740.53, 1) == 36.2, "SEC: $1,333,740.53 before; 36.2% kept")
check("OIT AIML" in sblk, "SEC: the award's description 'OIT AIML'")
pto = term["1333BJ24C00280005"]
check(amt(pto) == -624728.99 and pto["Action Date"] == "2026-08-20" and pto["Mod"] == "P26012", "USPTO: -$624,728.99 on 2026-08-20, mod P26012")
check(pto["Transaction Description"].strip() == "PATENT SEARCH ARTIFICIAL INTELLIGENCE DEVELOPMENT SECURITY OPERATIONS SUPPORT.", "USPTO: the termination line's title, quoted")
pblk = awards[awards.index("1333BJ24C00280005"):]; pblk = pblk[:pblk.index("\n==")]
check("obligated 27753766.76 " in pblk and "base+all options 55322899.54" in pblk, "USPTO: $27,753,766.76 obligated of a $55,322,899.54 ceiling")
check(round(27753766.76 + 624728.99, 2) == 28378495.75 and round(100 * 624728.99 / 28378495.75, 1) == 2.2, "USPTO: $28,378,495.75 before; 2.2% terminated")
check("PATENT SEARCH ARTIFICIAL INTELLIGENCE MODELS AND LABOR. THIS ACTION IS AWARDED PURSUANT TO THE USPTO EFFICIENCY ACT." in pblk, "USPTO: the award's text, quoted")
af = term["FA864924P1125"]
check(amt(af) == -449898.00 and af["Action Date"] == "2026-03-26" and af["Mod"] == "P00003", "Air Force: -$449,898.00 on 2026-03-26, mod P00003")
ablk = awards[awards.index("FA864924P1125"):]; ablk = ablk[:ablk.index("\n==")]
check("obligated 1349694.0 " in ablk, "Air Force: $1,349,694.00 left")
check(round(1349694.0 + 449898.0, 2) == 1799592.00 and 449898.0 / 1799592.0 == 0.25, "Air Force: $1,799,592.00 before; exactly 25.0%")
check("2024-08-16 .. 2025-12-16" in ablk, "Air Force: period of performance 2024-08-16 .. 2025-12-16 (the termination line is dated after it)")
check("SECURE LARGE LANGUAGE MODELS TO ENABLE GENERAL ARTIFICIAL INTELLIGENCE FOR CRITICAL DEPARTMENT OF THE AIR FORCE APPLICATIONS" in ablk, "Air Force: the award's text, quoted")
check(round(sum(amt(r) for r in bins["TERMINATION"]) / 1e6, 2) == -1.93, "the three terminations: $1.93 million between them")

print("== the vehicle")
try:
    rc = json.load(open(DATA / "vehicle_2032L225D00002_recheck.json", encoding="utf-8"))
    n = len(rc["search"].get("results", []))
    check(n == 1 and rc["search"]["results"][0]["Award ID"] == "2032L225F00049", "one award carries the vehicle's id in its text (live re-check %s): %d" % (rc["at"], n))
except FileNotFoundError:
    check(False, "vehicle re-check file missing (data/vehicle_2032L225D00002_recheck.json)")

print()
if FAILS:
    print("FAILED: %d figure(s) did not match the saved rows:" % len(FAILS))
    for f in FAILS:
        print("  - " + f)
    sys.exit(1)
print("every quoted figure matches the saved rows.")
