"""Tests for andlake.config."""

from __future__ import annotations

import pytest

from andlake.config import AndlakeConfig, get_config, reset_config


# ---------------------------------------------------------------------------
# Fixtures
# ---------------------------------------------------------------------------

# Full env vars — includes optional overrides for defaults.
FULL_ENV = {
    "ANDLAKE_GATEWAY_URL": "http://custom-gateway:9090",
    "TRINO_HOST": "custom-gateway",
    "TRINO_PORT": "9090",
    "NESSIE_URI": "http://nessie-custom:19120/api/v2",
    "MLFLOW_TRACKING_URI": "http://mlflow-custom:5001",
    "ANDLAKE_DEFAULT_CATALOG": "my_catalog",
    "ANDLAKE_S3_BUCKET": "my-bucket",
    "ANDLAKE_TENANT_ID": "tenant-abc",
    "ANDLAKE_ACCESS_TOKEN": "eyJhbGciOi.test.token",
}


@pytest.fixture(autouse=True)
def _clean_config():
    """Reset the module-level config singleton between tests."""
    reset_config()
    yield
    reset_config()


# ---------------------------------------------------------------------------
# Tests — from_env() with defaults (no env vars set at all)
# ---------------------------------------------------------------------------


class TestAndlakeConfigDefaults:
    """When no env vars are set, all fields get sane defaults."""

    def test_defaults_applied(self, monkeypatch: pytest.MonkeyPatch):
        # Clear any existing env vars
        for key in FULL_ENV:
            monkeypatch.delenv(key, raising=False)

        cfg = AndlakeConfig.from_env()

        assert cfg.gateway_url == "http://notebook-service:8082"
        assert cfg.trino_host == "notebook-service"
        assert cfg.trino_port == 8082
        assert cfg.nessie_uri == "http://nessie:19120/api/v2"
        assert cfg.mlflow_tracking_uri == "http://mlflow:5000"
        assert cfg.default_catalog == "lake"
        assert cfg.s3_bucket == "andlake-app"
        assert cfg.tenant_id == ""
        assert cfg.access_token == ""


# ---------------------------------------------------------------------------
# Tests — from_env() with full overrides
# ---------------------------------------------------------------------------


class TestAndlakeConfigOverrides:
    """All env vars can be overridden."""

    def test_all_overrides(self, monkeypatch: pytest.MonkeyPatch):
        for key, val in FULL_ENV.items():
            monkeypatch.setenv(key, val)

        cfg = AndlakeConfig.from_env()

        assert cfg.gateway_url == "http://custom-gateway:9090"
        assert cfg.trino_host == "custom-gateway"
        assert cfg.trino_port == 9090
        assert cfg.nessie_uri == "http://nessie-custom:19120/api/v2"
        assert cfg.mlflow_tracking_uri == "http://mlflow-custom:5001"
        assert cfg.default_catalog == "my_catalog"
        assert cfg.s3_bucket == "my-bucket"
        assert cfg.tenant_id == "tenant-abc"
        assert cfg.access_token == "eyJhbGciOi.test.token"


# ---------------------------------------------------------------------------
# Tests — frozen dataclass
# ---------------------------------------------------------------------------


class TestAndlakeConfigImmutable:
    """Config is frozen — attributes cannot be modified after creation."""

    def test_frozen(self):
        cfg = AndlakeConfig.from_env()

        with pytest.raises(AttributeError):
            cfg.tenant_id = "other"  # type: ignore[misc]


# ---------------------------------------------------------------------------
# Tests — get_config() singleton
# ---------------------------------------------------------------------------


class TestGetConfig:
    """get_config() caches and returns the same instance."""

    def test_singleton(self):
        cfg1 = get_config()
        cfg2 = get_config()

        assert cfg1 is cfg2

    def test_reset_clears_cache(self):
        cfg1 = get_config()
        reset_config()
        cfg2 = get_config()

        # Same values, but a fresh object
        assert cfg1 == cfg2
        assert cfg1 is not cfg2
