"""Minimalní FastAPI starter — pouze 127.0.0.1, API klíč auth, CORS jen localhost,
omezování rychlosti (rate limiting), limit velikosti těla požadavku."""

from __future__ import annotations

import os
import time
from collections import deque
from typing import Annotated

from fastapi import FastAPI, HTTPException, Request, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from pydantic import BaseModel

API_KEY = os.environ.get("DEV_ENV_API_KEY")
if not API_KEY:
    raise RuntimeError("Proměnná prostředí DEV_ENV_API_KEY je povinná (žádné výchozí hodnoty, žádné secret v kódu).")

MAX_BODY_BYTES = 1_048_576  # 1 MiB
RATE_LIMIT_WINDOW_SECONDS = 60
RATE_LIMIT_MAX_REQUESTS = 60
ALLOWED_ORIGINS = ["http://127.0.0.1", "http://localhost"]

app = FastAPI(
    title="Dev-Env Starter API",
    docs_url=None,   # Swagger UI vypnutý ve výchozím nastavení
    redoc_url=None,
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=ALLOWED_ORIGINS,
    allow_credentials=False,
    allow_methods=["GET", "POST"],
    allow_headers=["Authorization", "Content-Type"],
)

# In-memory rate limiter: {client_ip: deque[timestamps]}
_rate_limit_state: dict[str, deque[float]] = {}


def _client_ip(request: Request) -> str:
    return request.client.host if request.client else "unknown"


def _check_rate_limit(client_ip: str) -> None:
    now = time.monotonic()
    window = _rate_limit_state.setdefault(client_ip, deque())
    while window and now - window[0] >= RATE_LIMIT_WINDOW_SECONDS:
        window.popleft()
    if len(window) >= RATE_LIMIT_MAX_REQUESTS:
        raise HTTPException(
            status_code=status.HTTP_429_TOO_MANY_REQUESTS,
            detail="Limit rychlosti byl překročen.",
        )
    window.append(now)


@app.middleware("http")
async def security_middleware(request: Request, call_next):
    # 1. API klíč auth (Api-Key schéma)
    auth = request.headers.get("authorization", "")
    prefix = "Api-Key "
    provided = auth[len(prefix):] if auth.startswith(prefix) else ""
    if provided != API_KEY:
        return JSONResponse(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Neplatný nebo chybějící API klíč.",
        )

    # 2. Omezení rychlosti podle IP klienta
    _check_rate_limit(_client_ip(request))

    # 3. Limit velikosti těla požadavku (přečíst tělo a nahradit receive pro downstream)
    body = await request.body()
    if len(body) > MAX_BODY_BYTES:
        return JSONResponse(
            status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
            detail="Tělo požadavku je příliš velké.",
        )

    async def receive() -> dict:
        return {"type": "http.request", "body": body, "more_body": False}

    from starlette.requests import Request as StarletteRequest

    request = StarletteRequest(request.scope, receive)
    response = await call_next(request)
    return response


class GenerateRequest(BaseModel):
    prompt: str
    max_tokens: int = 512


@app.post("/generate")
async def generate(payload: Annotated[GenerateRequest, ...]) -> dict:
    return {"status": "ok", "echo": payload.prompt[:100], "max_tokens": payload.max_tokens}


@app.get("/health")
async def health() -> dict:
    return {"status": "healthy"}


if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="127.0.0.1", port=8080)
