"""Smoke test: extract just the scen_* helpers from app.py and run them
against real data. Compare to the standalone _abc_3scenarios.py output
(scenario B: cancel=59, postpone=23, 7 sanity flips)."""
import ast
import pandas as pd
import numpy as np

# Pull the scen_* helpers out of app.py without importing streamlit
src = open("app.py", encoding="utf-8").read()
tree = ast.parse(src)
helpers_src = []
for node in tree.body:
    if isinstance(node, ast.FunctionDef) and node.name.startswith("scen_"):
        helpers_src.append(ast.get_source_segment(src, node))
ns = {"np": np, "pd": pd}
exec("\n\n".join(helpers_src), ns)
print(f"Loaded {len(helpers_src)} helpers: "
      + ", ".join(n for n in ns if n.startswith("scen_")))

# ---- Unit tests on real_weeks_cover ----
print("\n=== real_weeks_cover unit tests ===")
rwc = ns["scen_real_weeks_cover"]
print(f"  stock=1000, dem=[100,100,100] → {rwc(1000, [100, 100, 100]):.2f} (expected 10.0)")
print(f"  stock=250, dem=[100,100,100] → {rwc(250, [100, 100, 100]):.2f} (expected 2.5)")
print(f"  stock=100, dem=[0,0,100] → {rwc(100, [0, 0, 100]):.2f} (expected 3.0)")
print(f"  stock=0, dem=[100] → {rwc(0, [100]):.2f} (expected 0.0)")

# ---- classify ----
print("\n=== classify unit tests ===")
cl = ns["scen_classify"]
print(f"  cov_now=5, post=30, cancel=26 → {cl(5, 30, 26)} (expected CANCEL)")
print(f"  cov_now=5, post=20, cancel=26 → {cl(5, 20, 26)} (expected POSTPONE)")
print(f"  cov_now=3, post=10, cancel=26 → {cl(3, 10, 26)} (expected REVIEW)")
print(f"  cov_now=1, post=5, cancel=26 → {cl(1, 5, 26)} (expected PRODUCE)")
print(f"  cov_now=5, post=30, cancel=None → {cl(5, 30, None)} (expected POSTPONE)")

# ---- Full Scenario B replication ----
print("\n=== Scenario B replication on real data ===")
CY, CW = 2026, 20
HORIZON = 13
PO_WINDOW_YWS = {2026 * 100 + w for w in range(22, 28)}

inc = pd.read_csv("data/incoming_supply.csv")
sup = pd.read_csv("data/supply_master.csv")
sup["is_abc"] = sup["supplier"].fillna("").str.contains("ABC NUTRITIONAL", case=False)
inc_m = inc.merge(sup[["sku", "supplier", "is_abc"]], on="sku", how="left")
inc_m["is_abc"] = inc_m["is_abc"].fillna(False).astype(bool)
inc_m["yw"] = inc_m["year"] * 100 + inc_m["week"]

stock = pd.read_csv("data/stock.csv")
wh_map = dict(zip(stock["sku"], stock["on_hand"]))
fc = pd.read_csv("data/forecast_for_supply.csv")
fc["yw"] = fc["year"] * 100 + fc["week"]
fc_lookup = {(r.sku, r.yw): float(r.demand) for r in fc.itertuples()}

abc_window = inc_m[inc_m["is_abc"] & inc_m["yw"].isin(PO_WINDOW_YWS)].copy()

rwc = ns["scen_real_weeks_cover"]
cl = ns["scen_classify"]
ws = ns["scen_week_series"]
sc = ns["scen_sanity_check"]

rows = []
for _, po in abc_window.iterrows():
    sku = po["sku"]
    py, pw = int(po["year"]), int(po["week"])
    qty = float(po["qty"])
    wh = float(wh_map.get(sku, 0))
    series_now = [fc_lookup.get((sku, y * 100 + w), 0.0) for (y, w) in ws(CY, CW, HORIZON)]
    cn = rwc(wh, series_now)
    series_post = [fc_lookup.get((sku, y * 100 + w), 0.0) for (y, w) in ws(py, pw, HORIZON)]
    cp = rwc(wh + qty, series_post)
    rows.append({"sku": sku, "po_year": py, "po_week": pw, "qty": int(qty),
                 "action_raw": cl(cn, cp, 26, 4)})
pdf = pd.DataFrame(rows)
walk_weeks = ws(CY, CW, HORIZON)
pdf["action"], flips = sc(pdf, "action_raw", inc_m, fc_lookup, wh_map, walk_weeks, 4)

raw_counts = pdf["action_raw"].value_counts().to_dict()
final_counts = pdf["action"].value_counts().to_dict()
print(f"  POs in scope: {len(pdf)}")
print(f"  Raw classification: {raw_counts}")
print(f"  Post-sanity: {final_counts}")
print(f"  Sanity flips: {len(flips)}")
print()
print("Standalone script reported (scenario B, post-sanity): cancel=59, postpone=23, 7 flips")
print("Match?", "YES ✅" if (final_counts.get('CANCEL', 0) == 59
      and final_counts.get('POSTPONE', 0) == 23 and len(flips) == 7) else "NO ❌")
