import re
from typing import Optional

_PHONE_RE = re.compile(r'^\(\d{3}\) \d{3}-\d{4}$')
_PASSWORD_SYMBOLS = "!@#$%^&*()_+-=[]{}|;:,.<>?/~`\"'\\"


def validate_phone(v: Optional[str]) -> Optional[str]:
    """Accept None/empty or a formatted US/CA phone: (NXX) NXX-XXXX."""
    if v is None or v == '':
        return v
    if not _PHONE_RE.match(v):
        raise ValueError('Phone must be formatted as (NXX) NXX-XXXX — e.g. (613) 555-0100')
    return v


def validate_password_strength(v: str) -> str:
    """Enforce the platform password policy (INDL-55): min 8 chars, at least
    one uppercase, one lowercase, one digit, and one symbol.

    Raises ValueError naming every unmet rule (not just the first) so the
    caller can surface a complete inline error in one round trip. Returns the
    original string unchanged when valid.
    """
    errors = []
    if len(v) < 8:
        errors.append("at least 8 characters")
    if len(v.encode("utf-8")) > 72:
        errors.append("no more than 72 bytes")
    if not any(c.isupper() for c in v):
        errors.append("at least one uppercase letter")
    if not any(c.islower() for c in v):
        errors.append("at least one lowercase letter")
    if not any(c.isdigit() for c in v):
        errors.append("at least one digit")
    if not any(c in _PASSWORD_SYMBOLS for c in v):
        errors.append("at least one symbol (e.g. !@#$%^&*)")
    if errors:
        raise ValueError("Password must contain " + ", ".join(errors))
    return v
