#!/usr/bin/env python3
"""Independently verify the supplied fulfillment analysis without external packages."""
import csv
import json
import math
from pathlib import Path

root = Path(__file__).resolve().parent
process = json.loads((root / "process.json").read_text())
cycle = json.loads((root / "tool-cycle-time.json").read_text())
detector = json.loads((root / "tool-bottlenecks.json").read_text())
stages = process["stages"]
assert len(stages) == 6
assert [s["type"] for s in stages] == ["value-add", "wait", "value-add", "wait", "rework", "value-add"]
assert all(0 <= s["duration_minutes_p50"] <= s["duration_minutes_p90"] for s in stages)
sum50 = sum(s["duration_minutes_p50"] for s in stages)
sum90 = sum(s["duration_minutes_p90"] for s in stages)
by_type = {
    t: {q: sum(s[f"duration_minutes_{q}"] for s in stages if s["type"] == t)
        for q in ("p50", "p90")}
    for t in ("value-add", "wait", "rework")
}
assert sum50 == cycle["total_p50_minutes"] == 780
assert sum90 == cycle["total_p90_minutes"] == 2310
assert cycle["profile"] == detector["profile"] == "services"
assert cycle["stage_count"] == 6
for t, prefix in [("value-add", "value_add"), ("wait", "wait"), ("rework", "rework")]:
    assert by_type[t]["p50"] == cycle[f"{prefix}_minutes_p50"]
    assert round(by_type[t]["p50"] / sum50, 4) == cycle[f"{prefix}_ratio"]
assert by_type["value-add"]["p50"] / sum50 < .08
assert cycle["verdict"] == "WASTE-HEAVY"
assert cycle["wip"] == process["wip"] == 8
proxy = process["wip"] / (sum50 / 60)
assert round(proxy, 4) == cycle["throughput_per_hour"]

mean_work = by_type["value-add"]["p50"] / sum(s["type"] == "value-add" for s in stages)
threshold = 2.5 * mean_work
expected_findings = []
for s in stages:
    if s["duration_minutes_p50"] > threshold:
        ratio = s["duration_minutes_p50"] / mean_work
        severity = "CRITICAL" if ratio >= 7.5 else "HIGH" if ratio >= 5 else "MEDIUM"
        expected_findings.append(("R1", "Slow stage: " + s["name"], severity, s["duration_minutes_p50"]))
wait_share = by_type["wait"]["p50"] / sum50
if wait_share > .5:
    severity = "CRITICAL" if wait_share >= 1 else "HIGH" if wait_share >= .75 else "MEDIUM"
    expected_findings.append(("R2", "Process is dominated by wait time", severity, by_type["wait"]["p50"]))
assert by_type["rework"]["p50"] / sum50 < .15
expected_findings.sort(key=lambda f: ({"CRITICAL": 0, "HIGH": 1, "MEDIUM": 2}[f[2]], -f[3]))
actual_findings = [(f["rule"], f["title"], f["severity"], f["impact_minutes_p50"]) for f in detector["findings"]]
assert actual_findings == expected_findings

expected = {}
for i, s in enumerate(stages, 1):
    expected[f"stage_{i}_p50"] = s["duration_minutes_p50"]
    expected[f"stage_{i}_p90"] = s["duration_minutes_p90"]
    expected[f"stage_{i}_share"] = s["duration_minutes_p50"] / sum50 * 100
expected["sum_stage_p50"] = sum50
expected["sum_stage_p90"] = sum90
for t, numbers in by_type.items():
    expected[t + "_p50_sum"] = numbers["p50"]
    expected[t + "_p90_sum"] = numbers["p90"]
    expected[t + "_share"] = numbers["p50"] / sum50 * 100
active50 = by_type["value-add"]["p50"] + by_type["rework"]["p50"]
active90 = by_type["value-add"]["p90"] + by_type["rework"]["p90"]
target = stages[1]["duration_minutes_p50"] / 2
scenario = sum50 - stages[1]["duration_minutes_p50"] + target
expected.update({
    "active_work_p50_sum": active50,
    "active_work_p90_sum": active90,
    "rework_share_of_active_work": by_type["rework"]["p50"] / active50 * 100,
    "picking_wait_share_of_wait": stages[1]["duration_minutes_p50"] / by_type["wait"]["p50"] * 100,
    "value_add_stage_mean": mean_work,
    "services_r1_threshold": threshold,
    "unvalidated_throughput_proxy": proxy,
    "pilot_scenario_picking_wait": target,
    "pilot_scenario_total": scenario,
    "pilot_scenario_reduction": (sum50 - scenario) / sum50 * 100,
})
with (root / "calculations.csv").open(newline="") as handle:
    rows = list(csv.DictReader(handle))
assert len(rows) == len(expected) == 39
assert {r["metric"] for r in rows} == set(expected)
for row in rows:
    assert math.isclose(float(row["value"]), expected[row["metric"]], abs_tol=1e-8), row["metric"]
with (root / "pilot-event-log.csv").open(newline="") as handle:
    reader = csv.DictReader(handle)
    assert "labor_minutes" in reader.fieldnames
    assert list(reader) == []
with (root / "pilot-scorecard.csv").open(newline="") as handle:
    scorecard = list(csv.DictReader(handle))
assert len(scorecard) == 9 and all(not row["observed_result"] for row in scorecard)

print("PASS: Six stages, 39 calculation rows, four ranked tool findings, services thresholds and planning scenario independently verified.")
print("PASS: Pilot ledger contains no observations; all nine scorecard result cells remain blank.")
print("Interpretation: Stage-percentile totals and snapshot-based throughput are planning arithmetic, not measured end-to-end percentiles or capacity.")
