"""
Serve the SERIES CARD locally — the page and the one route behind it, and nothing else.

    python -m v3.broadcast.live.serve_standings --event trwc_2026
    #  http://localhost:8766/core/web/standings.html      the card
    #  http://localhost:8766/standings.json               what it reads

This exists so the card needs no deployment and no simulator. The route lives in the producer, so
any producer serves it — but the two that exist locally both bring a race with them (`bridge_3d`
starts a simulated one, `serve_v3_live` needs the database), and a standings card wants neither. It
is the same shape as `serve_live.py`: a thin driver around `LiveFeedServer`.

WHERE THE NUMBERS COME FROM IS EVENT DATA, and this reads it from the event's own definition rather
than holding a URL of its own — `--event trwc_2026` is the module under `v3/events/`, exactly as
`python -m v3.events.publish` names it. A second championship is a different `--event` and no edit
here. `--url` overrides for a one-off, and `$VR_STANDINGS_URL` for a shell that already has it.

It publishes one header so the card gets what the race office cannot tell it: the event's name, and
the venue zone its stamp is written in. That is the whole reason the card holds no feed connection.
"""
from __future__ import annotations

import argparse
import importlib
import sys
import threading
from pathlib import Path

_HERE = Path(__file__).resolve().parent
if str(_HERE) not in sys.path:
    sys.path.insert(0, str(_HERE))
if str(_HERE.parent.parent / "ingest") not in sys.path:
    sys.path.insert(0, str(_HERE.parent.parent / "ingest"))
if str(_HERE.parents[2]) not in sys.path:                 # repo root, for `v3.events.*`
    sys.path.insert(0, str(_HERE.parents[2]))

from live_feed_server import LiveFeedServer, standings_binding_from_env  # noqa: E402

DEFAULT_PORT = 8766


def event_facts(module_name: str | None) -> tuple[dict, dict]:
    """`(standings binding, header meta)` from an event definition under `v3/events/`.

    Returns empty dicts for no event, which is a working state: the card then draws whatever
    `$VR_STANDINGS_URL` / `--url` points at, without an event's name above it.
    """
    if not module_name:
        return {}, {}
    module = importlib.import_module(f"v3.events.{module_name}")
    from event_config import integration_for  # noqa: PLC0415 — after the sys.path work above

    config = getattr(module, "EVENT_CONFIG", {}) or {}
    binding = (integration_for(config, "standings") or {}).get("config") or {}
    presentation = config.get("presentation") or {}
    # The same three keys `event_meta.overlay_event_config` puts on the wire for the race picture,
    # and for the same reasons: the event's name, the zone its stamp is written in, and who
    # sanctions it. Read here rather than invented, so an event declaring no sanctioning body simply
    # has none — the corner is not a place with a default in it.
    meta = {"eventName": config.get("name"), "venue": config.get("venue") or {},
            "sanctionMark": presentation.get("sanctionMark")}
    return binding, meta


def main(argv: list[str] | None = None) -> int:
    ap = argparse.ArgumentParser(description=__doc__.splitlines()[1])
    ap.add_argument("--event", help="event definition module under v3/events/, e.g. trwc_2026")
    ap.add_argument("--url", help="the published ranking page, overriding the event's binding")
    ap.add_argument("--source", help="who published it, for the card's attribution line")
    ap.add_argument("--host", default="127.0.0.1")
    ap.add_argument("--port", type=int, default=DEFAULT_PORT)
    a = ap.parse_args(argv)

    binding, meta = event_facts(a.event)
    # Precedence, weakest first: the event's binding, then the environment, then the flags. An
    # operator's explicit argument always wins over a document.
    binding = {**binding, **standings_binding_from_env()}
    if a.url:
        binding["rankingUrl"] = a.url
    if a.source:
        binding["displayName"] = a.source
    if not binding.get("rankingUrl"):
        ap.error("no standings source — pass --event with a `standings` binding, or --url")

    srv = LiveFeedServer(host=a.host, port=a.port, standings=binding)
    if meta.get("eventName"):
        # The producer normally learns these from the race plane. There is no race here, so publish
        # the header the card needs and nothing more.
        srv.publish_init(meta={**meta, "instanceId": "standings"}, course={}, teams=[])

    base = f"http://{'localhost' if a.host in ('127.0.0.1', '0.0.0.0') else a.host}:{a.port}"
    print(f"series card : {base}/core/web/standings.html")
    print(f"its data    : {base}/standings.json")
    print(f"reading     : {binding['rankingUrl']}")
    threading.Thread(target=srv.serve_forever, daemon=True).start()
    try:
        threading.Event().wait()
    except KeyboardInterrupt:
        srv.shutdown()
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
