"""pull_moe.py  (AUTHOR SIDE)

Adds the margins of error for the count based tables to a second snapshot.

The original snapshot carries the margin for median household income alone,
which would have forced Exercise IV-A to propagate one input and treat the
other three as exact. The summary file publishes a margin beside every
estimate, so the honest cascade is available for the cost of one more pull.

Written as a separate file so the original snapshot and every check value
already computed against it stay valid.

    python pull_moe.py
"""
from __future__ import annotations

import hashlib
import io
import json
from pathlib import Path

import pandas as pd
import requests

ROOT = Path(__file__).resolve().parent.parent
SNAP = ROOT / "snapshots"
YEAR, STATE = 2023, "28"
BASE = (f"https://www2.census.gov/programs-surveys/acs/summary_file/{YEAR}"
        f"/table-based-SF/data/5YRData/acsdt5y{YEAR}-{{t}}.dat")
SUMLEV = {"050": "county", "140": "tract", "150": "block group"}

WANT = {
    "b25044": ["B25044_E001", "B25044_M001", "B25044_E003", "B25044_M003",
               "B25044_E010", "B25044_M010"],
    "c17002": ["C17002_E001", "C17002_M001", "C17002_E002", "C17002_M002",
               "C17002_E003", "C17002_M003"],
    "b01001": (["B01001_E001", "B01001_M001"]
               + [f"B01001_{k}{n:03d}" for n in list(range(20, 26))
                  + list(range(44, 50)) for k in ("E", "M")]),
}


def load(table):
    print(f"  downloading {table} ...", flush=True)
    r = requests.get(BASE.format(t=table), timeout=900)
    r.raise_for_status()
    df = pd.read_csv(io.BytesIO(r.content), sep="|", dtype={"GEO_ID": str},
                     low_memory=False)
    keep = ["GEO_ID"] + [c for c in WANT[table] if c in df.columns]
    df = df[keep].copy()
    df["sumlev"] = df["GEO_ID"].str[:3]
    df = df[df["sumlev"].isin(SUMLEV)]
    df["code"] = df["GEO_ID"].str.split("US").str[-1]
    df = df[df["code"].str.startswith(STATE)]
    return df.drop(columns=["GEO_ID"])


if __name__ == "__main__":
    SNAP.mkdir(parents=True, exist_ok=True)
    frames = [load(t) for t in WANT]
    m = frames[0]
    for f in frames[1:]:
        m = m.merge(f.drop(columns=["sumlev"]), on="code", how="outer")
    m["level"] = m["sumlev"].map(SUMLEV)
    out = SNAP / f"acs{YEAR}_mississippi_moe.csv"
    m.to_csv(out, index=False)
    digest = hashlib.sha256(out.read_bytes()).hexdigest()
    (SNAP / "moe_manifest.json").write_text(json.dumps({
        "file": out.name, "rows": int(len(m)), "cols": int(m.shape[1]),
        "sha256": digest, "vintage": f"ACS {YEAR} 5-year"}, indent=2))
    print(f"\nfrozen: {out}\nrows {len(m)}  sha256 {digest[:32]}")
