import re
from typing import Literal, Optional

from pydantic import BaseModel, EmailStr, field_validator

_PHONE_RE = re.compile(r"^(\(\d{3}\)\s?\d{3}-\d{4}|\+1\d{10})$")


def _is_valid_name(v: str) -> bool:
    """Letters, spaces, hyphens, apostrophes only (Unicode-aware equivalent of ^[\\p{L} '\\-]+$)."""
    return all(ch.isalpha() or ch in " '-" for ch in v)

TOPIC_VALUES = (
    "finding_record",
    "memorial_tribute",
    "pre_need_plot",
    "service_arrangement",
    "genealogy_research",
    "other",
)


class CemeteryContactRequest(BaseModel):
    topic: Literal[
        "finding_record",
        "memorial_tribute",
        "pre_need_plot",
        "service_arrangement",
        "genealogy_research",
        "other",
    ]
    sender_name: str
    sender_email: EmailStr
    sender_phone: Optional[str] = None
    person_or_plot: Optional[str] = None
    message: str
    subscribe_newsletter: bool = False
    website: Optional[str] = None  # honeypot field

    @field_validator("sender_name")
    @classmethod
    def validate_sender_name(cls, v: str) -> str:
        v = v.strip()
        if len(v) < 2 or len(v) > 255:
            raise ValueError("Please enter your full name")
        if not _is_valid_name(v):
            raise ValueError("Please enter your full name")
        return v

    @field_validator("sender_email")
    @classmethod
    def validate_sender_email(cls, v: EmailStr) -> EmailStr:
        if len(str(v)) > 255:
            raise ValueError("Please enter a valid email address")
        return v

    @field_validator("sender_phone")
    @classmethod
    def validate_sender_phone(cls, v: Optional[str]) -> Optional[str]:
        if v is None or v == "":
            return v
        if not _PHONE_RE.match(v):
            raise ValueError("Please enter a valid phone number")
        return v

    @field_validator("person_or_plot")
    @classmethod
    def validate_person_or_plot(cls, v: Optional[str]) -> Optional[str]:
        if v is None:
            return v
        v = v.strip()
        if len(v) > 255:
            raise ValueError("Person or plot must not exceed 255 characters")
        return v or None

    @field_validator("message")
    @classmethod
    def validate_message(cls, v: str) -> str:
        if len(v) < 10:
            raise ValueError("Message must be at least 10 characters")
        if len(v) > 5000:
            raise ValueError("Message must not exceed 5000 characters")
        return v
