"""Input-Validators für die FastAPI-Endpoints.

Eigenes Modul, damit die Unit-Tests die Helper direkt importieren können
ohne den vollen FastAPI-/slowapi-Stack aus app.main mitzuziehen. Issue
#57 Befunde #3 (Path-Traversal via drucksache) und #7 (Search-Query-DoS).
"""
from __future__ import annotations

import re

from fastapi import HTTPException


# Drucksache-Format: erlaubt sind alle bisher in den 10 aktiven Bundesländern
# beobachteten Schreibweisen — z.B. "8/6390", "18/12345", "8/6390(neu)",
# "23/3700-A". Restriktiv genug, um Path-Traversal (../, /etc/passwd) und
# trivial-injection (?, ;, <, >, &, =) abzufangen.
_DRUCKSACHE_RE = re.compile(r"^\d{1,3}/\d{1,7}([-(].{1,20})?$")


def validate_drucksache(drucksache: str) -> str:
    """Lehnt jede Drucksache-ID ab, die nicht dem erwarteten Format
    entspricht. Gemeinsamer Validation-Funnel für alle Endpoints, die
    ``drucksache`` als Parameter nehmen. Issue #57 Befund #3.
    """
    if not drucksache or not _DRUCKSACHE_RE.match(drucksache):
        raise HTTPException(
            status_code=400,
            detail=f"Ungültige Drucksache-ID: {drucksache!r}",
        )
    return drucksache


# Längen-Limit für freie Search-Queries — verhindert, dass jemand mit einem
# 10-MB-Query die SQL-LIKE-Pattern oder den HTTP-Adapter aushungert.
# Issue #57 Befund #7.
MAX_SEARCH_QUERY_LEN = 200


def validate_search_query(q: str) -> str:
    if q is None:
        raise HTTPException(status_code=400, detail="Suchbegriff fehlt")
    if len(q) > MAX_SEARCH_QUERY_LEN:
        raise HTTPException(
            status_code=400,
            detail=f"Suchbegriff zu lang (max {MAX_SEARCH_QUERY_LEN} Zeichen, war {len(q)})",
        )
    return q
