"""Static configuration schema registry for Ilum platform modules.

Provides typed field definitions that the API and UI use to render
configuration forms.  Follows the same frozen-dataclass pattern as
``MODULE_REGISTRY`` in :mod:`ilum.core.modules`.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any

# ---------------------------------------------------------------------------
# Data classes
# ---------------------------------------------------------------------------


@dataclass(frozen=True)
class ConfigField:
    """Descriptor for a single configurable field within a module."""

    path: str
    """Dot-separated Helm values path, e.g. ``"resources.requests.memory"``."""

    label: str
    """Human-readable label shown in the UI."""

    field_type: str
    """Widget type: ``"text"``, ``"number"``, ``"select"``, ``"toggle"``,
    or ``"password"``."""

    description: str
    """Short help text displayed alongside the field."""

    default: Any = None
    """Default value used when the field is not explicitly set."""

    min_value: float | None = None
    """Minimum allowed value (applies to ``"number"`` fields)."""

    max_value: float | None = None
    """Maximum allowed value (applies to ``"number"`` fields)."""

    options: tuple[str, ...] = ()
    """Allowed choices (applies to ``"select"`` fields)."""

    tab: str = "advanced"
    """Tab assignment: ``"general"``, ``"resources"``, ``"storage"``, or ``"advanced"``."""

    hidden: bool = False
    """If True, excluded from API response (used to suppress auto-generated fields)."""


@dataclass(frozen=True)
class ConfigSchema:
    """Collection of configurable fields for a single module."""

    module_name: str
    """Module name matching ``ModuleDefinition.name``."""

    fields: tuple[ConfigField, ...]
    """Ordered tuple of fields exposed by this module."""


# ---------------------------------------------------------------------------
# Common resource fields shared by most modules
# ---------------------------------------------------------------------------

_COMMON_FIELDS: tuple[ConfigField, ...] = (
    ConfigField(
        path="replicaCount",
        label="Replica Count",
        field_type="number",
        description="Number of pod replicas to run.",
        default=1,
        min_value=1,
        max_value=10,
        tab="general",
    ),
    ConfigField(
        path="resources.requests.memory",
        label="Memory Request",
        field_type="select",
        description="Minimum memory guaranteed to each pod.",
        default="2Gi",
        options=("1Gi", "2Gi", "4Gi", "8Gi", "16Gi"),
        tab="resources",
    ),
    ConfigField(
        path="resources.requests.cpu",
        label="CPU Request",
        field_type="select",
        description="Minimum CPU guaranteed to each pod.",
        default="1",
        options=("0.5", "1", "2", "4"),
        tab="resources",
    ),
    ConfigField(
        path="resources.limits.memory",
        label="Memory Limit",
        field_type="select",
        description="Maximum memory a pod may use.",
        default="4Gi",
        options=("2Gi", "4Gi", "8Gi", "16Gi", "32Gi"),
        tab="resources",
    ),
    ConfigField(
        path="resources.limits.cpu",
        label="CPU Limit",
        field_type="select",
        description="Maximum CPU a pod may use.",
        default="2",
        options=("1", "2", "4", "8"),
        tab="resources",
    ),
)

# ---------------------------------------------------------------------------
# Module-specific extra fields
# ---------------------------------------------------------------------------

_MINIO_EXTRA = ConfigField(
    path="persistence.size",
    label="Storage Size",
    field_type="select",
    description="Persistent volume size for MinIO data.",
    default="10Gi",
    options=("10Gi", "50Gi", "100Gi", "500Gi"),
    tab="storage",
)

_MONITORING_EXTRA = ConfigField(
    path="grafana.adminPassword",
    label="Grafana Admin Password",
    field_type="password",
    description="Admin password for the Grafana dashboard.",
    default="admin",
    tab="advanced",
)

# ---------------------------------------------------------------------------
# Registry
# ---------------------------------------------------------------------------

# Modules that only expose the common resource fields.
_COMMON_ONLY_MODULES: tuple[str, ...] = (
    "jupyter",
    "jupyterhub",
    "zeppelin",
    "airflow",
    "kestra",
    "n8n",
    "nifi",
    "mageai",
    "superset",
    "mlflow",
    "streamlit",
    "langfuse",
    "trino",
    "gitea",
)

CONFIG_SCHEMA_REGISTRY: dict[str, ConfigSchema] = {
    name: ConfigSchema(module_name=name, fields=_COMMON_FIELDS) for name in _COMMON_ONLY_MODULES
}

# Modules with extra fields on top of the common set.
CONFIG_SCHEMA_REGISTRY["minio"] = ConfigSchema(
    module_name="minio",
    fields=_COMMON_FIELDS + (_MINIO_EXTRA,),
)
CONFIG_SCHEMA_REGISTRY["monitoring"] = ConfigSchema(
    module_name="monitoring",
    fields=_COMMON_FIELDS + (_MONITORING_EXTRA,),
)


# ---------------------------------------------------------------------------
# Public lookup helper
# ---------------------------------------------------------------------------


def get_config_schema(module_name: str) -> ConfigSchema | None:
    """Return the :class:`ConfigSchema` for *module_name*, or ``None``."""
    return CONFIG_SCHEMA_REGISTRY.get(module_name)
