"""Naming convention configuration for Prism.

Defines how generated code names variables, classes, tables, endpoints,
and other identifiers. Users can customize naming conventions per-project
instead of relying on hardcoded defaults.
"""

from __future__ import annotations

from enum import StrEnum

from pydantic import BaseModel, Field


class CaseStyle(StrEnum):
    """Supported case styles for naming."""

    SNAKE_CASE = "snake_case"
    CAMEL_CASE = "camelCase"
    PASCAL_CASE = "PascalCase"
    KEBAB_CASE = "kebab-case"
    SCREAMING_SNAKE = "SCREAMING_SNAKE_CASE"


class PluralStyle(StrEnum):
    """How to handle pluralization in naming."""

    PLURAL = "plural"
    SINGULAR = "singular"


class TableNamingConfig(BaseModel):
    """Database table naming conventions."""

    style: CaseStyle = Field(
        default=CaseStyle.SNAKE_CASE,
        description="Case style for table names",
    )
    plural: PluralStyle = Field(
        default=PluralStyle.SINGULAR,
        description="Whether table names are pluralized",
    )
    prefix: str = Field(
        default="",
        description="Prefix for all table names (e.g. 'app_')",
    )

    model_config = {"extra": "forbid"}


class ColumnNamingConfig(BaseModel):
    """Database column naming conventions."""

    style: CaseStyle = Field(
        default=CaseStyle.SNAKE_CASE,
        description="Case style for column names",
    )
    foreign_key_suffix: str = Field(
        default="_id",
        description="Suffix for foreign key columns",
    )
    timestamp_names: dict[str, str] = Field(
        default_factory=lambda: {
            "created": "created_at",
            "updated": "updated_at",
            "deleted": "deleted_at",
        },
        description="Custom names for timestamp columns",
    )

    model_config = {"extra": "forbid"}


class EndpointNamingConfig(BaseModel):
    """REST API endpoint naming conventions."""

    style: CaseStyle = Field(
        default=CaseStyle.KEBAB_CASE,
        description="Case style for URL path segments",
    )
    plural: PluralStyle = Field(
        default=PluralStyle.PLURAL,
        description="Whether endpoint paths are pluralized",
    )
    prefix: str = Field(
        default="/api/v1",
        description="URL prefix for REST endpoints",
    )

    model_config = {"extra": "forbid"}


class ClassNamingConfig(BaseModel):
    """Python/TypeScript class naming conventions."""

    model_suffix: str = Field(
        default="",
        description="Suffix for SQLAlchemy model classes (e.g. 'Model')",
    )
    schema_suffix: str = Field(
        default="",
        description="Suffix for Pydantic schema base classes (e.g. 'Schema')",
    )
    service_suffix: str = Field(
        default="Service",
        description="Suffix for service classes",
    )
    router_suffix: str = Field(
        default="Router",
        description="Suffix for REST router/controller identifiers",
    )

    model_config = {"extra": "forbid"}


class VariableNamingConfig(BaseModel):
    """Variable and function naming conventions."""

    backend_style: CaseStyle = Field(
        default=CaseStyle.SNAKE_CASE,
        description="Case style for Python variables and functions",
    )
    frontend_style: CaseStyle = Field(
        default=CaseStyle.CAMEL_CASE,
        description="Case style for TypeScript variables and functions",
    )
    constant_style: CaseStyle = Field(
        default=CaseStyle.SCREAMING_SNAKE,
        description="Case style for constants",
    )

    model_config = {"extra": "forbid"}


class NamingConfig(BaseModel):
    """Project-wide naming convention configuration.

    Controls how generators name tables, columns, endpoints, classes,
    variables, and files in the generated project. Provides a single
    place to define naming rules instead of scattering conventions
    across individual generators.

    Example:
        >>> naming = NamingConfig(
        ...     tables=TableNamingConfig(prefix="app_", plural=PluralStyle.PLURAL),
        ...     endpoints=EndpointNamingConfig(style=CaseStyle.SNAKE_CASE),
        ...     abbreviations={"organization": "org", "configuration": "config"},
        ... )
    """

    tables: TableNamingConfig = Field(
        default_factory=TableNamingConfig,
        description="Database table naming conventions",
    )
    columns: ColumnNamingConfig = Field(
        default_factory=ColumnNamingConfig,
        description="Database column naming conventions",
    )
    endpoints: EndpointNamingConfig = Field(
        default_factory=EndpointNamingConfig,
        description="REST endpoint naming conventions",
    )
    classes: ClassNamingConfig = Field(
        default_factory=ClassNamingConfig,
        description="Class naming conventions",
    )
    variables: VariableNamingConfig = Field(
        default_factory=VariableNamingConfig,
        description="Variable and function naming conventions",
    )
    abbreviations: dict[str, str] = Field(
        default_factory=dict,
        description="Custom abbreviation mappings (e.g. {'organization': 'org'})",
    )
    reserved_words: list[str] = Field(
        default_factory=lambda: [
            "type",
            "class",
            "import",
            "from",
            "return",
            "yield",
            "async",
            "await",
        ],
        description="Words to avoid or rename in generated identifiers",
    )

    model_config = {"extra": "forbid"}


__all__ = [
    "CaseStyle",
    "ClassNamingConfig",
    "ColumnNamingConfig",
    "EndpointNamingConfig",
    "NamingConfig",
    "PluralStyle",
    "TableNamingConfig",
    "VariableNamingConfig",
]
