"""
Input Validators
Validation utilities for common data types
"""
import re
from typing import Optional


def validate_phone(phone: str) -> bool:
    """
    Validate international phone number format.
    Expects format: +[country code][number] (e.g., +1234567890)
    """
    pattern = r"^\+[1-9]\d{6,14}$"
    return bool(re.match(pattern, phone))


def validate_email(email: str) -> bool:
    """Validate email address format"""
    pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
    return bool(re.match(pattern, email))


def validate_coordinates(latitude: float, longitude: float) -> bool:
    """Validate geographic coordinates"""
    return -90 <= latitude <= 90 and -180 <= longitude <= 180


def validate_password(password: str) -> tuple[bool, Optional[str]]:
    """
    Validate password strength.
    Returns (is_valid, error_message)
    """
    if len(password) < 8:
        return False, "Password must be at least 8 characters"
    if not any(c.isupper() for c in password):
        return False, "Password must contain at least one uppercase letter"
    if not any(c.islower() for c in password):
        return False, "Password must contain at least one lowercase letter"
    if not any(c.isdigit() for c in password):
        return False, "Password must contain at least one digit"
    return True, None


def sanitize_string(value: str) -> str:
    """Sanitize string input to prevent XSS"""
    import html
    return html.escape(value.strip())


def validate_license_plate(plate: str) -> bool:
    """Validate license plate format (basic validation)"""
    # Allow alphanumeric characters, spaces, and hyphens
    pattern = r"^[A-Z0-9\s\-]{2,15}$"
    return bool(re.match(pattern, plate.upper()))


def validate_promo_code(code: str) -> bool:
    """Validate promo code format"""
    # Alphanumeric, 3-20 characters
    pattern = r"^[A-Z0-9]{3,20}$"
    return bool(re.match(pattern, code.upper()))


def validate_otp(otp: str, length: int = 6) -> bool:
    """Validate OTP format"""
    return otp.isdigit() and len(otp) == length
