"""LLM routes — Sprint 2b: /echo ile streaming Claude çağrısı."""

from __future__ import annotations

import json
from collections.abc import AsyncIterator

from anthropic import APIError
from fastapi import APIRouter, HTTPException
from fastapi.responses import StreamingResponse
from pydantic import BaseModel, Field

from app.config import get_settings
from app.services.llm import (
    LLMNotConfiguredError,
    get_anthropic_client,
    load_turkpatent_system_prompt,
)

router = APIRouter(prefix="/llm", tags=["llm"])


class EchoRequest(BaseModel):
    message: str = Field(..., min_length=1, max_length=2000)
    model: str | None = Field(
        default=None,
        description="Override model; varsayılan ANTHROPIC_DEFAULT_MODEL (Haiku 4.5).",
    )
    max_tokens: int = Field(default=512, ge=16, le=4096)


def _sse_event(event: str, data: dict) -> str:
    """SSE (text/event-stream) format: 'event: X\\ndata: {...}\\n\\n'."""
    return f"event: {event}\ndata: {json.dumps(data, ensure_ascii=False)}\n\n"


async def _stream_claude(request: EchoRequest) -> AsyncIterator[str]:
    """Claude'a stream isteği at, gelen token'ları SSE olarak yay."""
    try:
        client = get_anthropic_client()
    except LLMNotConfiguredError as exc:
        yield _sse_event("error", {"message": str(exc)})
        return

    settings = get_settings()
    model = request.model or settings.anthropic_default_model
    system_prompt = load_turkpatent_system_prompt()

    try:
        async with client.messages.stream(
            model=model,
            max_tokens=request.max_tokens,
            # Sistem prompt'u cache_control ile işaretlendi — 5dk TTL, sonraki
            # istekler ~0.1x maliyetle cache'den okunur (cache_read_input_tokens).
            system=[
                {
                    "type": "text",
                    "text": system_prompt,
                    "cache_control": {"type": "ephemeral"},
                }
            ],
            messages=[{"role": "user", "content": request.message}],
        ) as stream:
            yield _sse_event("start", {"model": model})

            async for text in stream.text_stream:
                yield _sse_event("delta", {"text": text})

            final = await stream.get_final_message()
            yield _sse_event(
                "end",
                {
                    "stop_reason": final.stop_reason,
                    "usage": {
                        "input_tokens": final.usage.input_tokens,
                        "output_tokens": final.usage.output_tokens,
                        "cache_creation_input_tokens": getattr(
                            final.usage, "cache_creation_input_tokens", 0
                        )
                        or 0,
                        "cache_read_input_tokens": getattr(
                            final.usage, "cache_read_input_tokens", 0
                        )
                        or 0,
                    },
                },
            )
    except APIError as exc:
        yield _sse_event(
            "error",
            {"message": f"Anthropic API hatası: {exc.message}", "status": exc.status_code},
        )


@router.post("/echo")
async def llm_echo(request: EchoRequest) -> StreamingResponse:
    """Claude'a mesajı gönderir, token-by-token SSE stream döner.

    Frontend SSE client (eventsource-parser) bu endpoint'i dinleyebilir.
    Event tipleri:
    - start: {model}
    - delta: {text}
    - end:   {stop_reason, usage}
    - error: {message, status?}
    """
    settings = get_settings()
    if not settings.anthropic_api_key:
        # Config hatası — 503 dön (endpoint canlı ama servis konfigüre değil)
        raise HTTPException(
            status_code=503,
            detail="LLM servisi konfigüre edilmemiş (ANTHROPIC_API_KEY yok).",
        )

    return StreamingResponse(
        _stream_claude(request),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "X-Accel-Buffering": "no",  # nginx proxy buffering'i kapat
        },
    )
