"""Tests for the config schema registry."""

from __future__ import annotations

from ilum.core.config_schemas import (
    CONFIG_SCHEMA_REGISTRY,
    get_config_schema,
)
from ilum.core.modules import MODULE_REGISTRY


class TestConfigSchemaRegistry:
    def test_get_existing_schema(self) -> None:
        schema = get_config_schema("jupyter")
        assert schema is not None
        assert schema.module_name == "jupyter"
        assert len(schema.fields) > 0

    def test_get_unknown_schema_returns_none(self) -> None:
        assert get_config_schema("nonexistent") is None

    def test_get_module_without_schema_returns_none(self) -> None:
        # core is a valid module but has no config schema
        assert get_config_schema("core") is None

    def test_all_schemas_reference_valid_modules(self) -> None:
        module_names = {m.name for m in MODULE_REGISTRY}
        for name in CONFIG_SCHEMA_REGISTRY:
            assert name in module_names, f"Schema for '{name}' has no matching module"

    def test_field_types_valid(self) -> None:
        valid_types = {"text", "number", "select", "toggle", "password"}
        for name, schema in CONFIG_SCHEMA_REGISTRY.items():
            for field in schema.fields:
                assert field.field_type in valid_types, (
                    f"{name}.{field.path} has invalid type '{field.field_type}'"
                )

    def test_no_duplicate_paths_per_schema(self) -> None:
        for name, schema in CONFIG_SCHEMA_REGISTRY.items():
            paths = [f.path for f in schema.fields]
            assert len(paths) == len(set(paths)), f"Schema '{name}' has duplicate paths"

    def test_select_fields_have_options(self) -> None:
        for name, schema in CONFIG_SCHEMA_REGISTRY.items():
            for field in schema.fields:
                if field.field_type == "select":
                    assert len(field.options) > 0, (
                        f"{name}.{field.path} is select but has no options"
                    )

    def test_number_fields_have_range(self) -> None:
        for name, schema in CONFIG_SCHEMA_REGISTRY.items():
            for field in schema.fields:
                if field.field_type == "number":
                    assert field.min_value is not None or field.max_value is not None, (
                        f"{name}.{field.path} is number but has no range"
                    )

    def test_common_fields_present(self) -> None:
        """All schemas should have the 5 common resource fields."""
        common_paths = {
            "replicaCount",
            "resources.requests.memory",
            "resources.requests.cpu",
            "resources.limits.memory",
            "resources.limits.cpu",
        }
        for name, schema in CONFIG_SCHEMA_REGISTRY.items():
            schema_paths = {f.path for f in schema.fields}
            assert common_paths.issubset(schema_paths), (
                f"Schema '{name}' missing common fields: {common_paths - schema_paths}"
            )

    def test_minio_has_persistence_size(self) -> None:
        schema = get_config_schema("minio")
        assert schema is not None
        paths = {f.path for f in schema.fields}
        assert "persistence.size" in paths

    def test_monitoring_has_grafana_password(self) -> None:
        schema = get_config_schema("monitoring")
        assert schema is not None
        fields_by_path = {f.path: f for f in schema.fields}
        assert "grafana.adminPassword" in fields_by_path
        assert fields_by_path["grafana.adminPassword"].field_type == "password"

    def test_frozen_dataclasses(self) -> None:
        schema = get_config_schema("jupyter")
        assert schema is not None
        # ConfigSchema and ConfigField should be frozen
        import dataclasses

        assert dataclasses.is_dataclass(schema)
        assert dataclasses.is_dataclass(schema.fields[0])
