"""Memory-Endpoints (geteiltes Gedächtnis). LAN-only, kein Token in 2.0-Phase 3."""

import time

from fastapi import APIRouter, HTTPException
from pydantic import BaseModel

from services import memory
from services.voice_metrics import park, record_stage

router = APIRouter(prefix="/api")


class MemIn(BaseModel):
    content: str
    category: str = "knowledge"
    source: str = "manual"


class MemUp(BaseModel):
    content: str | None = None
    category: str | None = None


class DedupeIn(BaseModel):
    apply: bool = False
    threshold: float = 0.85


class LearnIn(BaseModel):
    text: str | None = None
    messages: list[dict] | None = None
    source: str = "auto"
    category: str = "knowledge"


@router.get("/memory/export")
def export() -> dict:
    return memory.export_text()


@router.get("/memory/graph")
def graph(min_score: float = 0.45, top_k: int = 3) -> dict:
    """Fakten als Ähnlichkeits-Graph (Knoten + semantische Kanten) für die Visualisierung."""
    return memory.graph(min_score=min_score, top_k=top_k)


@router.post("/memory/learn", status_code=201)
def learn(body: LearnIn) -> dict:
    """Auto-Lernen: Gesprächs-Turns/Text durchreichen → Mem0 extrahiert Fakten selbst."""
    return memory.learn(text=body.text, messages=body.messages,
                        source=body.source, category=body.category)


@router.post("/memory/dedupe")
def dedupe(body: DedupeIn) -> dict:
    return memory.dedupe(apply=body.apply, threshold=body.threshold)


@router.get("/memory")
def list_mem(q: str = "", category: str = "") -> list[dict]:
    # Semantischer Retrieve (q gesetzt) = u.a. Hermes' Mem0-Prefetch VOR jedem Turn. Dauer messen
    # + parken, damit der laufende Voice-Chat-Turn sie als Unter-Detail seiner Hirn-Zeit einsammelt.
    if q:
        _t0 = time.perf_counter()
        res = memory.list_memories(q=q, category=category)
        _ms = (time.perf_counter() - _t0) * 1000.0
        record_stage("memory_retrieve", _ms)
        park("retrieve", _ms)
        return res
    return memory.list_memories(q=q, category=category)


@router.post("/memory", status_code=201)
def add(body: MemIn) -> dict:
    if body.category not in memory.CATEGORIES:
        raise HTTPException(400, f"Kategorie '{body.category}' unbekannt.")
    return memory.add_memory(body.content, body.category, body.source)


@router.put("/memory/{mid}")
def update(mid: str, body: MemUp) -> dict:
    res = memory.update_memory(mid, content=body.content, category=body.category)
    if not res:
        raise HTTPException(404, "Eintrag nicht gefunden")
    return res


@router.delete("/memory/{mid}")
def delete(mid: str) -> dict:
    if not memory.delete_memory(mid):
        raise HTTPException(404, "Eintrag nicht gefunden")
    return {"ok": True}
