"""Notruf-Bridge: empfängt das Webhook-Payload des Voice Assistants und löst
über seven.io SMS und/oder einen Sprachanruf (Text-to-Speech) aus.

Kette:  App  --POST /notruf-->  diese Bridge  --seven_send-->  SMS / Anruf

Die eigentlichen seven.io-Aufrufe stecken in der wiederverwendbaren Library
`seven_send` (SevenClient). Diese Bridge ist nur der HTTP-Adapter für die
(asynchrone) App und ruft den synchronen Client via ``asyncio.to_thread``.

Konfiguration über Umgebungsvariablen (siehe emergency-bridge.env.example):
  SEVENIO_API_KEY     seven.io API-Key (Pflicht für echten Versand)
  BRIDGE_TOKEN        falls gesetzt: erwartet 'Authorization: Bearer <token>'
                      und muss EMERGENCY_WEBHOOK_TOKEN der App entsprechen
  SEVENIO_SMS_FROM    Absender-ID der SMS (Default "Notruf")
  SEVENIO_VOICE_FROM  Caller-ID des Anrufs (verifizierte Nummer; optional)
  SEVENIO_VOICE_NAME  SSML-Stimme für den Anruf (Default "de-de-female")
  BRIDGE_HOST/PORT    Bind-Adresse (Default 127.0.0.1:8090)
"""

import asyncio
import logging
import os

from fastapi import FastAPI, Header, HTTPException, Request
from seven_send import SevenClient

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("emergency_bridge")

app = FastAPI(title="Notruf-Bridge (seven.io)")


def _check_auth(authorization: str | None) -> None:
    """Prüft das Bearer-Token, falls BRIDGE_TOKEN gesetzt ist."""
    token = os.getenv("BRIDGE_TOKEN", "")
    if not token:
        return  # kein Token konfiguriert -> keine Prüfung
    if authorization != f"Bearer {token}":
        raise HTTPException(status_code=401, detail="ungültiges Bearer-Token")


def _make_client() -> SevenClient | None:
    """Baut den SevenClient aus der Env. None, wenn kein API-Key gesetzt ist."""
    api_key = os.getenv("SEVENIO_API_KEY", "")
    if not api_key:
        return None
    return SevenClient(
        api_key,
        sms_from=os.getenv("SEVENIO_SMS_FROM", "Notruf"),
        voice_from=os.getenv("SEVENIO_VOICE_FROM") or None,
        voice_name=os.getenv("SEVENIO_VOICE_NAME", "de-de-female"),
    )


async def _dispatch(client: SevenClient | None, channel: str, phone: str, text: str) -> dict:
    """Löst einen Kanal für eine Nummer aus (sync Client im Thread). Liefert ein Ergebnis-Dict."""
    if client is None:
        return {"phone": phone, "channel": channel, "ok": False, "info": "SEVENIO_API_KEY nicht gesetzt"}
    send = client.send_sms if channel == "sms" else client.send_voice
    res = await asyncio.to_thread(send, phone, text)
    return {"phone": phone, "channel": channel, "ok": res.ok, "info": res.error or res.code or "ok"}


@app.get("/health")
async def health() -> dict:
    return {"status": "ok", "configured": bool(os.getenv("SEVENIO_API_KEY"))}


@app.post("/notruf")
async def notruf(request: Request, authorization: str | None = Header(default=None)) -> dict:
    """Empfängt das Notruf-Payload der App und fächert es auf SMS/Anruf auf."""
    _check_auth(authorization)
    payload = await request.json()

    phones = payload.get("phones") or []
    channels = payload.get("channels") or ["sms", "call"]
    message = payload.get("message") or {}
    sms_text = message.get("sms") or ""
    call_text = message.get("call") or ""

    client = _make_client()
    results: list[dict] = []
    for phone in phones:
        if "sms" in channels and sms_text:
            results.append(await _dispatch(client, "sms", phone, sms_text))
        if "call" in channels and call_text:
            results.append(await _dispatch(client, "call", phone, call_text))

    any_ok = any(r["ok"] for r in results)
    logger.info("Notruf verarbeitet: %d Nummer(n), Ergebnisse=%s", len(phones), results)
    return {"received": True, "any_sent": any_ok, "results": results}
