"""{{name}} — tiny endpoint body ({{board}}).

Exposes exactly the worker's endpoint actions (chatgpt-plugin-tinyai ENDPOINT_ACTIONS):
    GET  /api/health            public
    GET  /api/telemetry         bearer
    GET  /api/camera/snapshot   bearer, image/jpeg (503 until a frame exists)
    POST /api/chat {prompt}     bearer → {result}

Auth: {{SLUG}}_TOKEN env, else ~/.{{slug}}/token. Fail closed once a token exists.
Replace `telemetry()`, `snapshot()` and `chat()` with the body's real readings, camera and agent.
"""
from __future__ import annotations

import os
import time
from pathlib import Path
from typing import Any, Dict, Optional

from fastapi import Body as _Body, FastAPI, HTTPException, Request, Response

BODY = "{{slug}}"
VERSION = "0.1.0"
BOOT = time.time()


def owner_token() -> Optional[str]:
    tok = os.environ.get("{{SLUG}}_TOKEN")
    if tok:
        return tok.strip()
    p = Path(os.environ.get("{{SLUG}}_HOME", str(Path.home() / ".{{slug}}"))) / "token"
    try:
        return p.read_text().strip() or None
    except OSError:
        return None


def _bearer(req: Request) -> Optional[str]:
    h = req.headers.get("authorization", "")
    if h.lower().startswith("bearer "):
        return h[7:].strip()
    return req.query_params.get("token") or req.cookies.get("{{slug}}_session")


def require(req: Request) -> str:
    """Who is calling: 'token' (the configured bearer) or 'loopback' (only while no token exists)."""
    want = owner_token()
    got = _bearer(req)
    if want:
        if got == want:
            return "token"
        raise HTTPException(401, {"error": "login required"})
    if req.client and req.client.host in ("127.0.0.1", "::1"):
        return "loopback"
    raise HTTPException(401, {"error": "no token configured — set {{SLUG}}_TOKEN"})


# ── the body ────────────────────────────────────────────────────────────────
def telemetry() -> Dict[str, Any]:
    """Flat, JSON-safe readings. Keep keys stable — the tiny app renders them as rows."""
    return {"body": BODY, "uptime_s": round(time.time() - BOOT), "t": time.time(), "state": "idle"}


def snapshot() -> Optional[bytes]:
    """Latest JPEG frame or None (→ 503). Wire the camera here."""
    return None


def chat(prompt: str) -> Dict[str, Any]:
    """One agent turn on the body. Wire the agent here; keep it depth-capped (no use_device)."""
    return {"result": f"{BODY} heard: {prompt[:200]}", "turns": 1}


# ── app ─────────────────────────────────────────────────────────────────────
app = FastAPI(title=BODY, version=VERSION)


@app.get("/api/health")
def health():
    return {"ok": True, "body": BODY, "version": VERSION, "auth": bool(owner_token())}


@app.get("/api/auth/login")
def login(req: Request, token: str = ""):
    want = owner_token()
    if not want or token != want:
        raise HTTPException(401, {"error": "bad token"})
    r = Response(status_code=303, headers={"Location": "/"})
    r.set_cookie("{{slug}}_session", want, httponly=True, samesite="lax")
    return r


@app.get("/api/telemetry")
def api_telemetry(req: Request):
    require(req)
    return telemetry()


@app.get("/api/camera/snapshot")
def api_snapshot(req: Request):
    require(req)
    frame = snapshot()
    if not frame:
        raise HTTPException(503, {"error": "no frame yet"})
    return Response(frame, media_type="image/jpeg")


@app.post("/api/chat")
def api_chat(req: Request, body: Dict[str, Any] = _Body(default={})):
    require(req)
    text = str(body.get("prompt") or body.get("text") or "").strip()[:600]
    if not text:
        raise HTTPException(422, {"error": "prompt required"})
    return chat(text)
