"""Where-am-I awareness — which network Ahmed is on = where he physically is.

macOS now HIDES the Wi-Fi SSID unless the app holds Location permission, so we
fingerprint the network the permission-free way: the default gateway's MAC
address (unique per router — his home router, the office, his phone hotspot are
all distinct). Each fingerprint is labelled once ("home"/"work"/"mobile") in
control/locations.json; after that Jarvis always knows where he is.

Ahmed's seed mapping (by his SSID names, which become the labels):
  Rajeh 5G      -> home   (his apartment)
  alrugaib      -> work   (the Alrugaib office)
  Nothing Phone -> mobile (phone hotspot / on the move)

Binding an unknown network: Jarvis writes control/loc_bind.json
{"place": "work", "label": "the office", "ssid": "alrugaib"} when Ahmed says
where he is; the ControlWatcher stores it against the current fingerprint.
"""
from __future__ import annotations

import json
import re
import subprocess
from pathlib import Path

_CONTROL = Path(__file__).resolve().parent.parent / "control"
_STORE = _CONTROL / "locations.json"

# spoken place -> human phrasing Jarvis can use
PLACES = {
    "home": "at home, in his apartment",
    "work": "at the Alrugaib office",
    "mobile": "out and about (on his phone hotspot)",
    "unknown": "somewhere new — an unrecognised network",
}


def _gateway_mac() -> str | None:
    """The default gateway's MAC — a stable, permission-free network id."""
    try:
        gw = None
        out = subprocess.run(["route", "-n", "get", "default"],
                             capture_output=True, text=True, timeout=4).stdout
        m = re.search(r"gateway:\s*([0-9.]+)", out)
        gw = m.group(1) if m else None
        if not gw:
            return None
        subprocess.run(["ping", "-c", "1", "-t", "1", gw],
                       capture_output=True, timeout=3)  # prime the arp cache
        arp = subprocess.run(["arp", "-n", gw], capture_output=True,
                             text=True, timeout=4).stdout
        m = re.search(r"([0-9a-f]{1,2}(?::[0-9a-f]{1,2}){5})", arp, re.I)
        return m.group(1).lower() if m else None
    except Exception:  # noqa: BLE001
        return None


def _load() -> dict:
    try:
        return json.loads(_STORE.read_text())
    except Exception:  # noqa: BLE001
        return {}


def _save(d: dict) -> None:
    try:
        _CONTROL.mkdir(exist_ok=True)
        _STORE.write_text(json.dumps(d, indent=1))
    except Exception:  # noqa: BLE001
        pass


def bind(place: str, label: str = "", ssid: str = "") -> str | None:
    """Label the CURRENT network as a place. Returns the fingerprint bound."""
    fp = _gateway_mac()
    if not fp:
        return None
    d = _load()
    d[fp] = {"place": place, "label": label or PLACES.get(place, place),
             "ssid": ssid}
    _save(d)
    return fp


def current() -> dict:
    """Where Ahmed is right now: {place, label, ssid, fingerprint, known}."""
    fp = _gateway_mac()
    if not fp:
        return {"place": "unknown", "label": "offline or wired",
                "known": False, "fingerprint": None}
    hit = _load().get(fp)
    if hit:
        return {**hit, "fingerprint": fp, "known": True}
    return {"place": "unknown", "label": PLACES["unknown"], "ssid": "",
            "fingerprint": fp, "known": False}


def seed_if_empty() -> None:
    """First run: assume the current network is home (Ahmed's 'Rajeh 5G'), so
    location works out of the box; work/mobile get bound when he's there."""
    if _load():
        return
    fp = _gateway_mac()
    if fp:
        _save({fp: {"place": "home", "label": "his apartment",
                    "ssid": "Rajeh 5G"}})
