"""Rebuild the published descriptive study from the public chart JSON.

python scripts/research/build_breadth_study.py INPUT.json OUTPUT_DIRECTORY
Uses Friday calendar observations, not an inferred exchange trading calendar.
Requires matplotlib for the shareable chart (tested with matplotlib 3.11.1).
The input is a fixed snapshot; no provider requests or backtests are performed.
"""
import csv
from datetime import datetime, timezone
import hashlib
import json
from pathlib import Path
import sys


def build(source, output):
    raw = source.read_bytes()
    points = json.loads(raw)["buy_fraction"]
    observations = {}
    for timestamp, value in points:
        day = datetime.fromtimestamp(timestamp / 1000, timezone.utc).date()
        if not 0 <= value <= 100:
            raise ValueError("Breadth must be between zero and 100")
        if day in observations:
            raise ValueError("Duplicate calendar observation")
        observations[day] = value
    weekly = [(day, value) for day, value in sorted(observations.items()) if day.weekday() == 4]
    output.mkdir(parents=True, exist_ok=True)
    with (output / "breadth-weekly-2026-09-05.csv").open("w", newline="", encoding="utf-8") as handle:
        writer = csv.writer(handle, lineterminator="\n")
        writer.writerow(["friday_date_utc", "stocks_above_six_month_ema_percent"])
        writer.writerows(weekly)
    annual = []
    for year in sorted({day.year for day, _ in weekly}):
        values = [value for day, value in weekly if day.year == year]
        annual.append({"year": year, "observations": len(values), "mean": round(sum(values) / len(values), 2),
                       "minimum": min(values), "maximum": max(values),
                       "below_25": sum(value < 25 for value in values),
                       "above_75": sum(value > 75 for value in values)})
    summary = {"source_url": "https://pyinvesting.com/fear-and-greed/cash-data",
               "retrieved_utc_date": "2026-09-05", "source_sha256": hashlib.sha256(raw).hexdigest(),
               "start": str(weekly[0][0]), "end": str(weekly[-1][0]), "observations": len(weekly),
               "below_25": sum(value < 25 for _, value in weekly),
               "above_75": sum(value > 75 for _, value in weekly), "annual": annual}
    (output / "breadth-study-summary.json").write_text(json.dumps(summary, indent=2) + "\n", encoding="utf-8", newline="\n")
    import matplotlib
    matplotlib.use("Agg")
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    plt.rcParams.update({"font.family": "DejaVu Sans", "svg.hashsalt": "pyinvesting-breadth-2026-09"})
    fig, ax = plt.subplots(figsize=(12, 5.5), dpi=160)
    fig.subplots_adjust(left=.075, right=.975, top=.78, bottom=.22)
    ax.plot([day for day, _ in weekly], [value for _, value in weekly], color="#245c74", linewidth=1.1)
    ax.set_ylim(0, 100)
    ax.set_yticks([0, 25, 50, 75, 100], labels=["0%", "25%", "50%", "75%", "100%"])
    ax.xaxis.set_major_locator(mdates.YearLocator(4))
    ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y"))
    ax.grid(axis="y", color="#dce3eb", linewidth=.8)
    ax.set_axisbelow(True)
    ax.tick_params(colors="#526277", length=0, pad=8)
    for spine in ax.spines.values():
        spine.set_visible(False)
    fig.text(.075, .92, "How widely is the uptrend shared?", color="#26364a", fontsize=21, weight="bold")
    fig.text(.075, .86, "Stocks above their six-month EMA · Weekly Friday observations", fontsize=12, color="#526277")
    fig.text(.075, .10, "Source: PyInvesting public breadth series · Fixed snapshot 5 September 2026", fontsize=10, color="#526277")
    fig.text(.075, .055, "Descriptive history, not a return forecast or a point-in-time universe claim. Data and method: pyinvesting.com/blog/", fontsize=9, color="#526277")
    fig.savefig(output / "breadth-weekly-2026-09-05.svg", metadata={"Date": None})
    svg = output / "breadth-weekly-2026-09-05.svg"
    svg.write_text("\n".join(line.rstrip() for line in svg.read_text(encoding="utf-8").splitlines()) + "\n",
                   encoding="utf-8", newline="\n")
    fig.savefig(output / "breadth-weekly-2026-09-05.png")
    plt.close(fig)
    print(json.dumps({key: value for key, value in summary.items() if key != "annual"}))


if __name__ == "__main__":
    build(Path(sys.argv[1]), Path(sys.argv[2]))
