"""Authentication and call metadata helpers."""

from __future__ import annotations

import re
from collections.abc import Iterable

Metadata = tuple[tuple[str, str], ...]
_SENSITIVE_HEADERS = frozenset({"x-api-key", "authorization", "proxy-authorization"})

_SENSITIVE_PATTERNS = (
    re.compile(
        r"(?i)((?:x-api-key|authorization|proxy-authorization)\s*[:=]\s*['\"])([^'\"\r\n]+)(['\"])"
    ),
    re.compile(
        r"(?i)((?:x-api-key|authorization|proxy-authorization)\s*[:=]\s*)(?!['\"])([^,\r\n;]+)"
    ),
)


def validate_api_key(api_key: str | None) -> None:
    if api_key is None:
        return
    if not api_key.strip():
        raise ValueError("api_key must be non-empty")
    if any(ch in api_key for ch in ("\n", "\r", "\x00")):
        raise ValueError("api_key contains invalid control characters")


def api_key_metadata(api_key: str | None) -> Metadata:
    validate_api_key(api_key)
    if api_key is None:
        return ()
    return (("x-api-key", api_key),)


def merge_metadata(base: Metadata, extra: Iterable[tuple[str, str]] | None) -> Metadata:
    if extra is None:
        return base
    merged = list(base)
    for key, value in extra:
        if not key or not value:
            raise ValueError("metadata keys and values must be non-empty")
        merged.append((key, value))
    return tuple(merged)


def is_sensitive_metadata_key(key: str) -> bool:
    return key.strip().lower() in _SENSITIVE_HEADERS


def redact_sensitive_text(text: str) -> str:
    redacted = text
    redacted = _SENSITIVE_PATTERNS[0].sub(r"\1<redacted>\3", redacted)
    redacted = _SENSITIVE_PATTERNS[1].sub(r"\1<redacted>", redacted)
    return redacted


def redact_metadata(metadata: Iterable[tuple[str, str]]) -> Metadata:
    sanitized: list[tuple[str, str]] = []
    for key, value in metadata:
        if is_sensitive_metadata_key(key):
            sanitized.append((key, "<redacted>"))
        else:
            sanitized.append((key, value))
    return tuple(sanitized)
