"""cooling_centers_analysis.py

DELIVERED CONSULTING ANALYSIS. Hinds County cooling center siting.
Prepared for the client. Ranks census tracts by need and recommends ten.

This file is the artifact students audit in Exercise II-B. It contains one
defect of substance and violates two of the strategic recommendations in
section 4.5 of the textbook. It runs cleanly and produces a professional
looking result, which is the point.

Instructors: do not correct this file. The generator that produces the
memorandum and the ranked table reads it, so editing one without the other
breaks the correspondence students verify.

    python cooling_centers_analysis.py
"""
from __future__ import annotations

import sys
from pathlib import Path

import numpy as np
import pandas as pd

sys.path.insert(0, str(Path(__file__).resolve().parent))
import common as C                                     # noqa: E402

COUNTY = "28049"
TOPN = 10
OUT = C.ROOT / "lab_artifacts"


def build():
    m = C.load_acs()

    bg = m[(m.level == "block group") & (m.code.str.startswith(COUNTY))].copy()
    bg["tract"] = bg["code"].str[:11]

    # Roll the block groups up to tract level.
    agg = bg.groupby("tract").agg(
        pop=("pop", "sum"),
        pop65=("pop65", "sum"),
        hh=("hh", "sum"),
        hh_nv=("hh_nv", "sum"),
        pov_univ=("pov_univ", "sum"),
        pov_below=("pov_below", "sum"),
        median_income=("medinc", "mean"),
    ).reset_index()

    agg["pct65"] = 100 * agg.pop65 / agg["pop"]
    agg["pct_nv"] = 100 * agg.hh_nv / agg.hh
    agg["pct_pov"] = 100 * agg.pov_below / agg.pov_univ
    agg = agg[(agg["pop"] > 0) & (agg.hh > 0) & (agg.pov_univ > 0)]

    # Need score. Four inputs, equally weighted percentile ranks.
    agg["income_rank"] = (-agg.median_income).rank(pct=True)
    agg["score"] = (agg.pct65.rank(pct=True)
                    + agg.pct_pov.rank(pct=True)
                    + agg.pct_nv.rank(pct=True)
                    + agg.income_rank)
    agg = agg.sort_values("score", ascending=False).reset_index(drop=True)
    agg["rank"] = np.arange(1, len(agg) + 1)
    return agg


def write_memo(agg):
    """The delivered memorandum, generated from the same numbers.

    Exercise II-B has students read this as a client before auditing the
    script behind it, so the memorandum must quote figures the script
    actually produced. Generating it here keeps the two from disagreeing,
    which is why the instructor note forbids hand-editing it.
    """
    from docx import Document
    from docx.enum.text import WD_ALIGN_PARAGRAPH
    from docx.shared import Pt, RGBColor

    top = agg.head(TOPN)
    doc = Document()
    st = doc.styles["Normal"]
    st.font.name, st.font.size = "Aptos", Pt(11)

    h = doc.add_paragraph("MEMORANDUM")
    h.runs[0].bold = True
    h.runs[0].font.size = Pt(16)
    h.alignment = WD_ALIGN_PARAGRAPH.CENTER
    doc.add_paragraph()
    for label, value in (
            ("To:", "Office of Emergency Management, Hinds County"),
            ("From:", "Delta Analytics Group"),
            ("Date:", "Prepared for the current planning cycle"),
            ("Subject:", "Cooling center siting, recommended locations")):
        p = doc.add_paragraph()
        p.add_run(f"{label}\t").bold = True
        p.add_run(value)
    doc.add_paragraph()

    doc.add_paragraph(
        f"We evaluated all {len(agg)} census tracts in Hinds County against "
        "four indicators of heat vulnerability: residents aged 65 and over, "
        "residents below poverty, households without access to a vehicle, and "
        "median household income. Each indicator was converted to a "
        "percentile rank across the county and the four ranks were summed "
        "with equal weight to produce a single need score. Tracts were then "
        "ordered by that score.")

    r = doc.add_paragraph().add_run("RECOMMENDATION")
    r.bold = True
    doc.add_paragraph(
        "We recommend siting cooling centers in the ten highest scoring "
        "tracts, listed below in priority order.")

    t = doc.add_table(rows=1, cols=6)
    t.style = "Table Grid"
    for c, name in zip(t.rows[0].cells,
                       ("Rank", "Tract", "Score", "Pct 65+",
                        "Pct poverty", "Median income")):
        c.text = name
        c.paragraphs[0].runs[0].bold = True
    for _, row in top.iterrows():
        cells = t.add_row().cells
        for c, v in zip(cells, (f"{row['rank']:.0f}", row["tract"],
                                f"{row['score']:.3f}", f"{row['pct65']:.1f}",
                                f"{row['pct_pov']:.1f}",
                                f"{row['median_income']:,.0f}")):
            c.text = str(v)

    doc.add_paragraph()
    doc.add_paragraph(
        f"The top ranked tract, {top.iloc[0]['tract']}, combines the highest "
        "elderly share in the county with substantial poverty and limited "
        "vehicle access. We are confident that these ten tracts represent the "
        "greatest concentration of heat vulnerable residents in Hinds County "
        "and that siting decisions can proceed on this basis.")
    doc.add_paragraph()
    doc.add_paragraph("Delta Analytics Group")
    doc.add_paragraph("Enclosure: cooling_centers_ranked.csv")

    path = OUT / "cooling_centers_memo.docx"
    doc.save(path)
    return path


def main():
    OUT.mkdir(exist_ok=True)
    agg = build()
    top = agg.head(TOPN)
    print("HINDS COUNTY COOLING CENTER SITING")
    print(f"tracts evaluated: {len(agg)}")
    print(f"\nRECOMMENDED {TOPN} TRACTS\n")
    print(f"{'rank':>5}{'tract':>14}{'score':>8}{'pct65':>8}{'pct pov':>9}"
          f"{'pct no veh':>12}{'median income':>15}")
    for _, r in top.iterrows():
        print(f"{r['rank']:>5.0f}{r['tract']:>14}{r['score']:>8.3f}"
              f"{r['pct65']:>8.1f}{r['pct_pov']:>9.1f}{r['pct_nv']:>12.1f}"
              f"{r['median_income']:>15,.0f}")
    cols = ["rank", "tract", "score", "pct65", "pct_pov", "pct_nv",
            "median_income", "pop"]
    agg[cols].to_csv(OUT / "cooling_centers_ranked.csv", index=False)
    print(f"\nwrote {OUT / 'cooling_centers_ranked.csv'}")
    print(f"wrote {write_memo(agg)}")


if __name__ == "__main__":
    main()
