"""Where the OBS-side tools look for the scene and the feed — one answer, not three.

`obs_boatcams`, `obs_boat_sources` and `gcp_gateway` each shipped their own `--base`/`--url` default,
and the three disagreed: `localhost:8766`, `localhost:8766/core/web/boatcam.html`, `localhost:8765`.
None of them is the producer. On race day the producer is a Cloud Run service and every one of those
defaults is a loopback address that will answer nothing — or, worse, answer from a stale local
process someone left running, which builds a perfectly valid OBS layout for the wrong race and looks
right until you read the sail numbers.

So the base is resolved in one place, from one variable, and a forgotten flag becomes an error rather
than a plausible picture:

    --base/--url on the command line   (explicit beats everything)
    $VR_PRODUCER_BASE                  (the deployment's answer — set this on the render machine)
    the local default                  (a developer running the whole stack on one box)

`VR_RACE_DAY=1` turns the last one into a refusal. It is the switch that says "this machine is
driving a real broadcast", and on such a machine a loopback base is never what was meant.
"""
from __future__ import annotations

import os
from urllib.parse import urlsplit

#: The single variable. Set it on the render machine to the producer's origin, e.g.
#: `https://trap-v3-producer-xxxx.a.run.app`.
ENV_VAR = "VR_PRODUCER_BASE"
#: "This machine is driving a live broadcast" — makes a loopback base an error, not a default.
RACE_DAY_VAR = "VR_RACE_DAY"

_LOOPBACK = {"localhost", "127.0.0.1", "::1", "0.0.0.0"}


class RaceDayBaseError(RuntimeError):
    """A loopback base on a machine declared to be running a real broadcast."""


def is_loopback(base: str) -> bool:
    """True when `base` points back at this machine — the shape a forgotten flag leaves behind."""
    host = urlsplit(base if "//" in base else f"//{base}").hostname
    return (host or "").lower() in _LOOPBACK


def resolve(cli_value: str | None, *, default: str, path: str = "") -> tuple[str, str]:
    """`(base, where_it_came_from)`, most-explicit first. Raises `RaceDayBaseError` if the result is
    loopback and `VR_RACE_DAY=1`.

    The source is returned rather than inferred because the caller logs it, and a log line that
    GUESSES where a value came from is worse than none — it is exactly the kind of confident wrong
    answer that sends someone looking in the wrong place at the wrong moment.

    `path` is appended when the answer came from the environment or the default, so a caller that
    wants a whole page URL (`…/core/web/boatcam.html`) still gets one from a bare origin. A value
    given on the command line is used exactly as typed — an operator who spells out a URL means it.
    """
    if cli_value:
        base, source = cli_value, "command line"
    else:
        env = (os.environ.get(ENV_VAR) or "").strip()
        base, source = ((env.rstrip("/") + path), f"${ENV_VAR}") if env else (default, "built-in default")
    if is_loopback(base) and os.environ.get(RACE_DAY_VAR) == "1":
        raise RaceDayBaseError(
            f"{RACE_DAY_VAR}=1 but the producer base is {base!r} (from the {source}), which points "
            f"at this machine. Set {ENV_VAR} to the producer's origin, or pass it explicitly — a "
            f"loopback base silently builds a valid layout for the wrong race.")
    return base, source
