"""Read-only: rank GSYS instances by actual boat movement, to find a real race."""
import math
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"


def bbox_diag_m(pts):
    if len(pts) < 2:
        return 0.0
    lat0 = sum(p[0] for p in pts) / len(pts)
    mlat, mlon = 111320.0, 111320.0 * math.cos(math.radians(lat0))
    xs = [p[1] * mlon for p in pts]
    ys = [p[0] * mlat for p in pts]
    return math.hypot(max(xs) - min(xs), max(ys) - min(ys))


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 and (md.get("toUtcMs") is None or gun <= md.get("toUtcMs")):
            return md.get("deviceId")
    return None


rows = []
for inst in db.collection("raceInstances").where(filter=FF("ownerUserId", "==", UID)).stream():
    d = inst.to_dict() or {}
    groups = list(db.collection("raceInstances").document(inst.id).collection("startGroups").stream())
    if not groups:
        continue
    g = groups[0]
    gd = g.to_dict() or {}
    gun = gd.get("officialStartUtcMs") or gd.get("startDateUtcMs") or d.get("loggingStartUtcMs")
    if not gun:
        continue
    ws, we = gun - 180_000, gun + 1_800_000
    devs = []
    for t in g.reference.collection("teamEntries").stream():
        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)
            if dev:
                devs.append(dev)
    moved = []
    for dev in set(devs):
        pts = []
        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) < ws or (td.get("startUtcMs") or 0) > we:
                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 ws <= t <= we and p.get("lat") is not None:
                        pts.append((p["lat"], p["lon"]))
        moved.append(round(bbox_diag_m(pts)))
    moved.sort(reverse=True)
    glocal = (datetime.fromtimestamp(gun / 1000, tz=UTC) + timedelta(hours=2)).strftime("%m-%d %H:%M")
    rows.append((inst.id, d.get("name"), len(devs), moved, glocal))

rows.sort(key=lambda r: -(sum(r[3]) if r[3] else 0))
print(f"{'instance':22} {'name':22} {'boats':5} {'gun+2':12} bbox-diag(m) per boat")
for iid, name, nb, moved, glocal in rows:
    print(f"{iid:22} {str(name)[:22]:22} {nb:<5} {glocal:12} {moved}")
