"""Tests for NamingConfig specification model."""

from __future__ import annotations

from prisme.spec.naming import (
    CaseStyle,
    ClassNamingConfig,
    ColumnNamingConfig,
    EndpointNamingConfig,
    NamingConfig,
    PluralStyle,
    TableNamingConfig,
    VariableNamingConfig,
)


class TestNamingConfigDefaults:
    """Test default values of NamingConfig."""

    def test_default_naming_config(self) -> None:
        cfg = NamingConfig()
        assert cfg.tables.style == CaseStyle.SNAKE_CASE
        assert cfg.tables.plural == PluralStyle.SINGULAR
        assert cfg.tables.prefix == ""
        assert cfg.columns.style == CaseStyle.SNAKE_CASE
        assert cfg.columns.foreign_key_suffix == "_id"
        assert cfg.endpoints.style == CaseStyle.KEBAB_CASE
        assert cfg.endpoints.plural == PluralStyle.PLURAL
        assert cfg.endpoints.prefix == "/api/v1"
        assert cfg.classes.model_suffix == ""
        assert cfg.classes.schema_suffix == ""
        assert cfg.classes.service_suffix == "Service"
        assert cfg.variables.backend_style == CaseStyle.SNAKE_CASE
        assert cfg.variables.frontend_style == CaseStyle.CAMEL_CASE
        assert cfg.variables.constant_style == CaseStyle.SCREAMING_SNAKE

    def test_default_timestamp_names(self) -> None:
        cfg = NamingConfig()
        assert cfg.columns.timestamp_names["created"] == "created_at"
        assert cfg.columns.timestamp_names["updated"] == "updated_at"
        assert cfg.columns.timestamp_names["deleted"] == "deleted_at"

    def test_default_reserved_words(self) -> None:
        cfg = NamingConfig()
        assert "type" in cfg.reserved_words
        assert "class" in cfg.reserved_words

    def test_empty_abbreviations_by_default(self) -> None:
        cfg = NamingConfig()
        assert cfg.abbreviations == {}


class TestNamingConfigCustomization:
    """Test custom values for NamingConfig."""

    def test_table_prefix(self) -> None:
        cfg = NamingConfig(tables=TableNamingConfig(prefix="app_"))
        assert cfg.tables.prefix == "app_"

    def test_plural_tables(self) -> None:
        cfg = NamingConfig(tables=TableNamingConfig(plural=PluralStyle.PLURAL))
        assert cfg.tables.plural == PluralStyle.PLURAL

    def test_snake_case_endpoints(self) -> None:
        cfg = NamingConfig(endpoints=EndpointNamingConfig(style=CaseStyle.SNAKE_CASE))
        assert cfg.endpoints.style == CaseStyle.SNAKE_CASE

    def test_model_suffix(self) -> None:
        cfg = NamingConfig(classes=ClassNamingConfig(model_suffix="Model"))
        assert cfg.classes.model_suffix == "Model"

    def test_abbreviations(self) -> None:
        cfg = NamingConfig(abbreviations={"organization": "org", "configuration": "config"})
        assert cfg.abbreviations["organization"] == "org"
        assert cfg.abbreviations["configuration"] == "config"

    def test_custom_timestamp_names(self) -> None:
        cfg = NamingConfig(
            columns=ColumnNamingConfig(
                timestamp_names={
                    "created": "creation_date",
                    "updated": "modification_date",
                    "deleted": "removal_date",
                }
            )
        )
        assert cfg.columns.timestamp_names["created"] == "creation_date"

    def test_custom_fk_suffix(self) -> None:
        cfg = NamingConfig(columns=ColumnNamingConfig(foreign_key_suffix="_fk"))
        assert cfg.columns.foreign_key_suffix == "_fk"

    def test_custom_reserved_words(self) -> None:
        cfg = NamingConfig(reserved_words=["type", "data"])
        assert cfg.reserved_words == ["type", "data"]


class TestNamingConfigValidation:
    """Test validation behavior."""

    def test_extra_fields_forbidden(self) -> None:
        import pytest
        from pydantic import ValidationError

        with pytest.raises(ValidationError):
            NamingConfig(unknown_field="value")  # type: ignore[call-arg]

    def test_table_config_extra_forbidden(self) -> None:
        import pytest
        from pydantic import ValidationError

        with pytest.raises(ValidationError):
            TableNamingConfig(unknown="value")  # type: ignore[call-arg]

    def test_variable_config_extra_forbidden(self) -> None:
        import pytest
        from pydantic import ValidationError

        with pytest.raises(ValidationError):
            VariableNamingConfig(unknown="value")  # type: ignore[call-arg]


class TestCaseStyleEnum:
    """Test CaseStyle enum values."""

    def test_all_styles_exist(self) -> None:
        assert CaseStyle.SNAKE_CASE == "snake_case"
        assert CaseStyle.CAMEL_CASE == "camelCase"
        assert CaseStyle.PASCAL_CASE == "PascalCase"
        assert CaseStyle.KEBAB_CASE == "kebab-case"
        assert CaseStyle.SCREAMING_SNAKE == "SCREAMING_SNAKE_CASE"


class TestPluralStyleEnum:
    """Test PluralStyle enum values."""

    def test_styles_exist(self) -> None:
        assert PluralStyle.PLURAL == "plural"
        assert PluralStyle.SINGULAR == "singular"
