"""Read-only discovery: list every GSYS race instance whose start-group gun falls
on 2026-05-23 or 2026-05-24, with course, gun times (UTC and +2h CEST), team count
and, per boat, the device id and how many GPS points it has near the gun. Used to
build race definitions for the May 23/24 GSYS 2v2 figure-of-8 ("digital 8") races."""
from datetime import UTC, datetime, timedelta

from google.cloud import firestore
from google.cloud.firestore_v1.base_query import FieldFilter as FF

db = firestore.Client(project="apps-viewregatta")
UID = "e5c5d08e-f8e9-4c2d-a6c3-3f6cc5d8d6d6"  # GSYS


def fmt(ms, off=0):
    if not ms:
        return "—"
    return (datetime.fromtimestamp(ms / 1000, tz=UTC) + timedelta(hours=off)).strftime("%Y-%m-%d %H:%M:%S")


def day_utc(ms):
    return datetime.fromtimestamp(ms / 1000, tz=UTC).strftime("%Y-%m-%d") if ms else None


def device_for_boat(boat_id, gun):
    if not boat_id:
        return None
    for m in db.collection("deviceMounts").where(filter=FF("boatId", "==", boat_id)).stream():
        md = m.to_dict() or {}
        if (md.get("fromUtcMs") or 0) <= (gun or 0) and (md.get("toUtcMs") is None or (gun or 0) <= md.get("toUtcMs")):
            return md.get("deviceId")
    return None


def count_points(dev, lo, hi):
    if not dev:
        return 0
    n = 0
    for tr in db.collection("tracks").where(filter=FF("deviceId", "==", dev)).stream():
        td = tr.to_dict() or {}
        if td.get("deletedAt") is not None:
            continue
        if (td.get("endUtcMs") or 0) < lo or (td.get("startUtcMs") or 0) > hi:
            continue
        for bb in db.collection("tracks").document(tr.id).collection("batches").stream():
            for p in (bb.to_dict() or {}).get("points", []):
                t = p.get("t") or 0
                if lo <= t <= hi and p.get("lat") is not None:
                    n += 1
    return n


course_name = {}
for c in db.collection("courses").where(filter=FF("ownerUserId", "==", UID)).stream():
    course_name[c.id] = (c.to_dict() or {}).get("name")

print("=== GSYS instances with a gun on 2026-05-23 or 2026-05-24 ===")
hits = []
for inst in db.collection("raceInstances").where(filter=FF("ownerUserId", "==", UID)).stream():
    d = inst.to_dict() or {}
    cid = d.get("courseId")
    groups = list(db.collection("raceInstances").document(inst.id).collection("startGroups").stream())
    for g in groups:
        gd = g.to_dict() or {}
        gun = gd.get("officialStartUtcMs")
        if day_utc(gun) in ("2026-05-23", "2026-05-24"):
            hits.append((inst.id, d, cid, g, gd, gun))

hits.sort(key=lambda h: h[5] or 0)
for inst_id, d, cid, g, gd, gun in hits:
    cn = course_name.get(cid) or "?"
    stop = gd.get("officialStopUtcMs")
    print(f"\ninstance {inst_id}  name={d.get('name')!r}  status={d.get('status')}")
    print(f"  course={cn!r} ({cid})  group={g.id[:8]} name={gd.get('name')!r}")
    print(f"  gunUTC={fmt(gun)}  gun+2(CEST)={fmt(gun,2)}  stopUTC={fmt(stop)}  stop+2={fmt(stop,2)}")
    lo, hi = (gun or 0) - 300_000, (stop or (gun or 0) + 900_000) + 60_000
    for t in g.reference.collection("teamEntries").stream():
        td = t.to_dict() or {}
        for b in t.reference.collection("boatEntries").stream():
            bd = b.to_dict() or {}
            dev = bd.get("deviceId") or device_for_boat(bd.get("boatId"), gun)
            pts = count_points(dev, lo, hi)
            print(f"    team={td.get('teamName')!r} sail={bd.get('sailId')!r} visual={bd.get('visualId')!r} "
                  f"dev={(dev or 'NONE')[:16]} pts={pts}")

print(f"\n{len(hits)} group(s) on 2026-05-23/24")
