"""Tests for CoreSettings configuration system."""

from functools import lru_cache

import pytest
from pydantic import ValidationError

from entr_adapter_core.config import CoreSettings


class TestCoreSettingsInstantiation:

    def test_all_fields_provided(self, monkeypatch):
        monkeypatch.setenv("TENANT_NAME", "TestTenant")
        monkeypatch.setenv("ENV", "production")
        monkeypatch.setenv("IS_TESTING", "false")

        settings = CoreSettings()
        assert settings.TENANT_NAME == "TestTenant"
        assert settings.ENV == "production"
        assert settings.IS_TESTING is False

    def test_default_values(self, monkeypatch):
        monkeypatch.setenv("TENANT_NAME", "TestTenant")
        # Don't set ENV or IS_TESTING — use defaults
        monkeypatch.delenv("ENV", raising=False)
        monkeypatch.delenv("IS_TESTING", raising=False)

        settings = CoreSettings()
        assert settings.TENANT_NAME == "TestTenant"
        assert settings.ENV == "local"
        assert settings.IS_TESTING is True

    def test_missing_required_field(self, monkeypatch):
        monkeypatch.delenv("TENANT_NAME", raising=False)
        monkeypatch.delenv("ENV", raising=False)
        monkeypatch.delenv("IS_TESTING", raising=False)

        with pytest.raises(ValidationError) as exc_info:
            CoreSettings(_env_file=None)

        error_str = str(exc_info.value)
        assert "TENANT_NAME" in error_str


class TestTenantExtension:

    def test_tenant_settings_with_all_fields(self, monkeypatch):
        class TenantSettings(CoreSettings):
            CUSTOM_ENDPOINT: str
            CUSTOM_TIMEOUT: int = 30

        monkeypatch.setenv("TENANT_NAME", "MyTenant")
        monkeypatch.setenv("CUSTOM_ENDPOINT", "https://api.example.com")

        settings = TenantSettings()
        assert settings.TENANT_NAME == "MyTenant"
        assert settings.ENV == "local"
        assert settings.CUSTOM_ENDPOINT == "https://api.example.com"
        assert settings.CUSTOM_TIMEOUT == 30

    def test_tenant_missing_field_clear_error(self, monkeypatch):
        class TenantSettings(CoreSettings):
            CUSTOM_FIELD: str

        monkeypatch.setenv("TENANT_NAME", "MyTenant")
        monkeypatch.delenv("CUSTOM_FIELD", raising=False)

        with pytest.raises(ValidationError) as exc_info:
            TenantSettings(_env_file=None)

        error_str = str(exc_info.value)
        assert "CUSTOM_FIELD" in error_str


class TestSingletonPattern:

    def test_lru_cache_returns_same_instance(self, monkeypatch):
        monkeypatch.setenv("TENANT_NAME", "TestTenant")

        @lru_cache()
        def get_settings() -> CoreSettings:
            return CoreSettings()

        try:
            s1 = get_settings()
            s2 = get_settings()
            assert s1 is s2
        finally:
            get_settings.cache_clear()


class TestModelCopy:

    def test_per_handler_override(self, monkeypatch):
        monkeypatch.setenv("TENANT_NAME", "TestTenant")
        monkeypatch.setenv("ENV", "local")

        settings = CoreSettings()
        override = settings.model_copy(update={"ENV": "production"})

        assert override.ENV == "production"
        assert settings.ENV == "local"  # Original not mutated


class TestEnvFileLoading:

    def test_loads_from_env_file(self, tmp_path):
        env_file = tmp_path / ".env"
        env_file.write_text("TENANT_NAME=FileLoadedTenant\n")

        settings = CoreSettings(_env_file=str(env_file))
        assert settings.TENANT_NAME == "FileLoadedTenant"
