"""
Input validation utilities for the Tallyfy SDK.

Provides centralized validation functions used across all management modules
to prevent injection attacks, path traversal, and data corruption from
malformed inputs.
"""

import re
from typing import Any

# Allowlist pattern for ID parameters: alphanumeric, hyphens, underscores.
# This covers all known Tallyfy ID formats (numeric, alphanumeric slugs, UUID-like).
_ID_PATTERN = re.compile(r'^[a-zA-Z0-9_\-]+$')

_MAX_ID_LENGTH = 255
_MAX_STRING_LENGTH = 10_000


def validate_id(value: Any, name: str) -> str:
    """
    Validate an ID parameter (org_id, run_id, task_id, group_id, etc.).

    Enforces a strict allowlist of alphanumeric characters, hyphens (-), and
    underscores (_) to prevent path traversal attacks and URL injection when
    IDs are embedded in API endpoint paths.

    Args:
        value: The value to validate.
        name: Parameter name used in error messages.

    Returns:
        The validated (stripped) string value.

    Raises:
        ValueError: If the value fails validation.
    """
    if not isinstance(value, str):
        raise ValueError(f"{name} must be a string, got {type(value).__name__}")
    value = value.strip()
    if not value:
        raise ValueError(f"{name} must be a non-empty string")
    if len(value) > _MAX_ID_LENGTH:
        raise ValueError(f"{name} must not exceed {_MAX_ID_LENGTH} characters")
    if not _ID_PATTERN.match(value):
        raise ValueError(
            f"{name} contains invalid characters. "
            "Only alphanumeric characters, hyphens (-), and underscores (_) are allowed."
        )
    return value


def validate_positive_int(value: Any, name: str) -> int:
    """
    Validate that a value is a positive integer.

    Args:
        value: The value to validate.
        name: Parameter name used in error messages.

    Returns:
        The validated integer value.

    Raises:
        ValueError: If the value is not a positive integer.
    """
    if isinstance(value, bool) or not isinstance(value, int) or value <= 0:
        raise ValueError(f"{name} must be a positive integer")
    return value


def validate_string(value: Any, name: str, max_length: int = _MAX_STRING_LENGTH) -> str:
    """
    Validate a non-empty string with an optional maximum length.

    Args:
        value: The value to validate.
        name: Parameter name used in error messages.
        max_length: Maximum allowed length (default: 10,000).

    Returns:
        The validated string value.

    Raises:
        ValueError: If the value fails validation.
    """
    if not isinstance(value, str):
        raise ValueError(f"{name} must be a string, got {type(value).__name__}")
    if not value.strip():
        raise ValueError(f"{name} must be a non-empty string")
    if len(value) > max_length:
        raise ValueError(f"{name} must not exceed {max_length} characters")
    return value
