#!/usr/bin/env python3
"""Capture the current Furkastrasse bau-cam image for local protocol use.

Runs silently on success so it is suitable for Hermes cron with no_agent=True.
Requires BAUCAM_USER and BAUCAM_PASS in the Hermes runtime environment.
"""
from __future__ import annotations

import base64
import datetime as dt
import hashlib
import json
import os
import re
import sys
import urllib.request
from pathlib import Path

BASE = "https://bau-cam.ch/schaffhausen/"
UA = "Mozilla/5.0 (X11; Linux x86_64) Hermes Furkastrasse webcam archive"
ROOT = Path("/home/agent/jarvis_memory/work/projects/furkastrasse/webcam")
INDEX = ROOT / "index.jsonl"
LATEST = ROOT / "latest.json"
SECRET_ENV = Path("/home/agent/.hermes/secrets/baucam_furkastrasse.env")


def _load_secret_env() -> None:
    """Load BAUCAM_* from a local 0600 env file if not already exported."""
    if os.environ.get("BAUCAM_USER") and os.environ.get("BAUCAM_PASS"):
        return
    if not SECRET_ENV.exists():
        return
    for line in SECRET_ENV.read_text(encoding="utf-8", errors="ignore").splitlines():
        line = line.strip()
        if not line or line.startswith("#") or "=" not in line:
            continue
        key, value = line.split("=", 1)
        key = key.strip().replace("export ", "")
        if key in {"BAUCAM_USER", "BAUCAM_PASS"} and key not in os.environ:
            os.environ[key] = value.strip().strip('"').strip("'")


def _fetch(path_or_url: str) -> tuple[dict, bytes]:
    url = path_or_url if path_or_url.startswith("http") else BASE + path_or_url.lstrip("/")
    _load_secret_env()
    user = os.environ.get("BAUCAM_USER")
    pw = os.environ.get("BAUCAM_PASS")
    if not user or not pw:
        raise RuntimeError("BAUCAM_USER/BAUCAM_PASS fehlen im Hermes-Environment")
    token = base64.b64encode(f"{user}:{pw}".encode()).decode()
    req = urllib.request.Request(url, headers={"User-Agent": UA, "Authorization": f"Basic {token}"})
    with urllib.request.urlopen(req, timeout=45) as r:
        return dict(r.headers), r.read()


def capture(now: dt.datetime | None = None) -> dict:
    now = now or dt.datetime.now().astimezone()
    # Safety guard even though cron is weekday-only.
    if now.weekday() >= 5:
        return {"skipped": True, "reason": "weekend", "timestamp": now.isoformat()}

    _, html = _fetch("live.php")
    text = html.decode("utf-8", "replace")
    m = re.search(r"bilder/\d+_TIMING\.jpg", text)
    if not m:
        raise RuntimeError("Kein aktuelles Webcam-Bild in live.php gefunden")
    remote_path = m.group(0)
    headers, img = _fetch(remote_path)
    if not img.startswith(b"\xff\xd8"):
        raise RuntimeError(f"Webcam-Antwort ist kein JPEG: content_type={headers.get('Content-Type')}")

    sha = hashlib.sha256(img).hexdigest()
    stamp = now.strftime("%Y-%m-%d_%H%M")
    month_dir = ROOT / now.strftime("%Y") / now.strftime("%m")
    month_dir.mkdir(parents=True, exist_ok=True)
    out = month_dir / f"{stamp}_furkastrasse_webcam.jpg"
    out.write_bytes(img)

    meta = {
        "timestamp": now.isoformat(),
        "date": now.strftime("%Y-%m-%d"),
        "time": now.strftime("%H:%M"),
        "path": str(out),
        "remote_path": remote_path,
        "source_url": BASE + remote_path,
        "bytes": len(img),
        "sha256": sha,
        "content_type": headers.get("Content-Type") or headers.get("content-type"),
        "purpose": "Furkastrasse internes BM/PL-Jourfix: aktueller Baustellenstand und Vergleichsanalyse",
    }
    ROOT.mkdir(parents=True, exist_ok=True)
    with INDEX.open("a", encoding="utf-8") as f:
        f.write(json.dumps(meta, ensure_ascii=False) + "\n")
    LATEST.write_text(json.dumps(meta, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
    return meta


def main() -> int:
    try:
        result = capture()
    except Exception as e:
        print(f"Furkastrasse Webcam Capture FEHLER: {e}", file=sys.stderr)
        return 1
    # Silent on normal success / weekend skip. Print only when explicitly requested.
    if "--print" in sys.argv:
        print(json.dumps(result, ensure_ascii=False, indent=2))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
