"""
arhs_matches_report.py -- [2026-10-01] The user: take the 150 playbook days most like ARHS at
9:35 (first 5 minutes), review each, mark the best entry and exit. Charts (same marks as the
library: best holdable buy/sell, 1% stop never hit; second move) + a summary of what those
150 days did after 9:35, and a PDF.
"""
import gzip
import json
import statistics as st
import sys
from collections import Counter
from datetime import datetime
from pathlib import Path
from zoneinfo import ZoneInfo

import matplotlib
matplotlib.use("Agg")
import matplotlib.dates as md
import matplotlib.pyplot as plt

HERE = Path(__file__).resolve().parent
TRADE = Path("/var/www/screener/trade")
sys.path.insert(0, str(TRADE)); sys.path.insert(0, str(HERE))
import reference as REF
import label_days as LD
from alpaca_client import get_client

ET = ZoneInfo("America/New_York")
OUT = HERE / "arhs_0935"
M = json.load(open(HERE / "arhs_0935_matches.json"))
MATCH_M = M["m"]


def draw(lab, B, path, rank=None, dist=None):
    ts = [x["t"].replace(tzinfo=None) for x in B]
    fig, (ax, axv) = plt.subplots(2, 1, figsize=(10.5, 5.0), gridspec_kw={"height_ratios": [3, 1]}, sharex=True)
    ax.plot(ts, [x["c"] for x in B], color="#1f3a5f", lw=1)
    ax.plot(ts, [x["vwap"] for x in B], color="#c0392b", lw=1.1)
    ax.axhline(B[0]["o"], color="grey", ls=":", lw=.8)
    t935 = B[0]["t"].replace(tzinfo=None, hour=9, minute=35, second=0)
    ax.axvline(t935, color="#e67e22", ls="--", lw=1)
    lo = min(x["l"] for x in B); hi = max(x["h"] for x in B); pad = (hi - lo) * .14
    ax.set_ylim(lo - pad, hi + pad)
    for key, col in (("best_held", "#16a085"), ("leg2", "#2980b9")):
        mk = lab.get(key)
        if not mk:
            continue
        bi = next(x for x in B if x["m"] == mk["entry_m"]); bj = next(x for x in B if x["m"] == mk["exit_m"])
        ax.scatter([bi["t"].replace(tzinfo=None)], [bi["c"]], marker="*", s=170, color=col, edgecolor="black", zorder=6)
        ax.scatter([bj["t"].replace(tzinfo=None)], [bj["c"]], marker="*", s=170, color="#8e44ad", edgecolor="black", zorder=6)
        ax.annotate(f"buy {bi['c']:.2f} ({bi['t']:%H:%M})", (bi["t"].replace(tzinfo=None), bi["c"]), xytext=(6, -14),
                    textcoords="offset points", fontsize=7, color=col, fontweight="bold")
        ax.annotate(f"sell {bj['c']:.2f} ({bj['t']:%H:%M}) +{mk['gain_pct']:.1f}%", (bj["t"].replace(tzinfo=None), bj["c"]),
                    xytext=(6, 7), textcoords="offset points", fontsize=7, color="#8e44ad", fontweight="bold")
    bh = lab.get("best_held")
    head = f"#{rank} " if rank else ""
    ax.set_title(f"{head}{lab['symbol']} {lab['date']}  open->close {lab['open_to_close_pct']:+.1f}%"
                 + (f"  | match distance {dist:.3f}" if dist is not None else "")
                 + ("  | NO GOOD TRADE" if lab["no_trade"] else f"  | best +{bh['gain_pct']:.1f}%: " + ", ".join(bh['entry']['tags'])
                    + " -> " + ", ".join(bh['exit']['tags'])), fontsize=7.5)
    ax.grid(alpha=.3)
    axv.bar(ts, [x["v"] for x in B], width=1 / 1440, color=["#8e44ad" if x["volx"] >= 10 else "#1f3a5f" for x in B])
    axv.xaxis.set_major_formatter(md.DateFormatter("%H:%M")); axv.grid(alpha=.3)
    plt.tight_layout(); plt.savefig(path, dpi=92); plt.close()


def main():
    OUT.mkdir(exist_ok=True)
    labels = {}
    want = {tuple(k.split("|")) for k in M["matches"]}
    for l in map(json.loads, open(LD.OUT)):
        if (l["date"], l["symbol"]) in want:
            labels[(l["date"], l["symbol"])] = l
    # ARHS itself
    d = datetime(2026, 10, 1, tzinfo=ET)
    raw = get_client().get_minute_bars("ARHS", start=d.replace(hour=9, minute=30), end=d.replace(hour=16), limit=1000)
    rows = [[int(b.timestamp.timestamp()), float(b.open), float(b.high), float(b.low), float(b.close), float(b.volume)] for b in raw]
    B = LD.build(rows, REF.load("2026-10-01", "ARHS"))
    arhs = LD.label("2026-10-01", "ARHS", B)
    draw(arhs, B, OUT / "000_ARHS_2026-10-01.png")
    stats = []
    by_date = {}
    for rank, (k, dist) in enumerate(zip(M["matches"], M["dist"]), 1):
        day, s = k.split("|")
        by_date.setdefault(day, []).append((rank, s, dist))
    for day, items in sorted(by_date.items()):
        dd = json.load(gzip.open(LD.BARS / f"bars_{day}.json.gz", "rt"))
        for rank, s, dist in items:
            ref = REF.load(day, s); lab = labels.get((day, s))
            if not ref or not lab:
                continue
            Bm = LD.build(dd["symbols"][s]["bars"], ref)
            draw(lab, Bm, OUT / f"{rank:03d}_{s}_{day}.png", rank, dist)
            c935 = next(x["c"] for x in Bm if x["m"] >= MATCH_M)
            up = dn = False
            for x in Bm:
                if x["m"] <= MATCH_M or x["m"] > 385:
                    continue
                if x["l"] <= c935 * .99: dn = True; break
                if x["h"] >= c935 * 1.02: up = True; break
            stats.append({"rank": rank, "lab": lab, "up": up, "dn": dn,
                          "close_from_935": (Bm[-1]["c"] / c935 - 1) * 100,
                          "max_from_935": (max(x["h"] for x in Bm if x["m"] > MATCH_M) / c935 - 1) * 100})
        REF._CACHE.clear()
    bh = [s["lab"]["best_held"] for s in stats if s["lab"]["best_held"]]
    em = [b["entry_m"] for b in bh]; xm = [b["exit_m"] for b in bh]
    hm = lambda m: f"{9 + (30 + m) // 60}:{(30 + m) % 60:02d}"
    summ = {
        "n": len(stats), "no_trade": sum(s["lab"]["no_trade"] for s in stats),
        "best_held_median": round(st.median(b["gain_pct"] for b in bh), 2),
        "best_buy_median": hm(int(st.median(em))), "best_sell_median": hm(int(st.median(xm))),
        "best_buy_before_935": sum(m < MATCH_M for m in em), "best_buy_935_1000": sum(MATCH_M <= m < 30 for m in em),
        "best_buy_1000_1100": sum(30 <= m < 90 for m in em), "best_buy_after_1100": sum(m >= 90 for m in em),
        "up_first_from_935": sum(s["up"] for s in stats), "down_first_from_935": sum(s["dn"] for s in stats),
        "close_from_935_median": round(st.median(s["close_from_935"] for s in stats), 2),
        "up_days": sum(s["lab"]["open_to_close_pct"] > 0 for s in stats),
        "buy_tags": Counter(t.split(" (")[0] for b in bh for t in b["entry"]["tags"]).most_common(4),
        "sell_tags": Counter(t.split(" (")[0].split(" 1")[0].split(" 2")[0].split(" 3")[0].split(" 4")[0].split(" 5")[0]
                             for b in bh for t in b["exit"]["tags"]).most_common(4),
        "arhs": {"best_held": arhs["best_held"]["gain_pct"] if arhs["best_held"] else None,
                 "buy": hm(arhs["best_held"]["entry_m"]) if arhs["best_held"] else None,
                 "sell": hm(arhs["best_held"]["exit_m"]) if arhs["best_held"] else None},
    }
    json.dump(summ, open(OUT / "summary.json", "w"), indent=1, default=str)
    print(json.dumps(summ, indent=1, default=str))


if __name__ == "__main__":
    main()
