"""Deployment preset data model and registry.

Provides curated deployment presets that bundle a set of modules and Helm
flags into named profiles (e.g. "default", "production").  Each preset
can optionally require user input for placeholder values at install time.
"""

from __future__ import annotations

from dataclasses import dataclass


@dataclass(frozen=True)
class DeploymentPreset:
    """Immutable descriptor for a named deployment profile.

    Attributes:
        name: Short identifier, e.g. ``"default"``, ``"production"``.
        description: One-line human-readable summary.
        modules: Modules to enable (references ``ModuleDefinition.name``).
        set_flags: Extra ``--set`` flags to pass to Helm.
        requires_input: Flag keys from *set_flags* whose placeholder value
            (e.g. ``<REGISTRY>``) must be replaced by the user before install.
    """

    name: str
    description: str
    modules: tuple[str, ...]
    set_flags: tuple[str, ...] = ()
    requires_input: tuple[str, ...] = ()


# ---------------------------------------------------------------------------
# Shared module sets
# ---------------------------------------------------------------------------

_DEFAULT_MODULES: tuple[str, ...] = (
    "core",
    "ui",
    "mongodb",
    "postgresql",
    "minio",
    "jupyter",
    "gitea",
    "hive-metastore",
    "sql",
    "marquez",
    "api",
)

# ---------------------------------------------------------------------------
# Preset definitions
# ---------------------------------------------------------------------------

_TINY = DeploymentPreset(
    name="tiny",
    description="Minimal footprint for resource-constrained environments",
    modules=("core", "ui", "mongodb", "postgresql", "minio", "jupyter", "gitea"),
)

_DEFAULT = DeploymentPreset(
    name="default",
    description="Standard setup matching chart defaults",
    modules=_DEFAULT_MODULES,
)

_DATA_ENGINEERING = DeploymentPreset(
    name="data-engineering",
    description="Full data stack with SQL, orchestration, and BI tooling",
    modules=_DEFAULT_MODULES + ("airflow", "superset", "trino"),
)

_ML_OPS = DeploymentPreset(
    name="ml-ops",
    description="Machine learning workflow with experiment tracking",
    modules=_DEFAULT_MODULES + ("mlflow", "airflow", "monitoring"),
)

_ANALYST = DeploymentPreset(
    name="analyst",
    description="Analytics and visualization for data analysts",
    modules=_DEFAULT_MODULES + ("superset", "trino", "streamlit"),
)

_PRODUCTION = DeploymentPreset(
    name="production",
    description="Hardened setup with security, monitoring, and replication",
    modules=_DEFAULT_MODULES + ("monitoring", "loki"),
    set_flags=(
        "global.security.enabled=true",
        "ilum-core.replicaCount=2",
    ),
)

_AIR_GAPPED = DeploymentPreset(
    name="air-gapped",
    description="Offline deployment with a private container registry",
    modules=("core", "ui", "mongodb", "postgresql", "minio", "jupyter", "gitea"),
    set_flags=("global.imageRegistry=<REGISTRY>",),
    requires_input=("global.imageRegistry",),
)

# ---------------------------------------------------------------------------
# Public registry
# ---------------------------------------------------------------------------

PRESETS: dict[str, DeploymentPreset] = {
    _TINY.name: _TINY,
    _DEFAULT.name: _DEFAULT,
    _DATA_ENGINEERING.name: _DATA_ENGINEERING,
    _ML_OPS.name: _ML_OPS,
    _ANALYST.name: _ANALYST,
    _PRODUCTION.name: _PRODUCTION,
    _AIR_GAPPED.name: _AIR_GAPPED,
}


def list_presets() -> list[DeploymentPreset]:
    """Return all presets in display order."""
    return list(PRESETS.values())


def get_preset(name: str) -> DeploymentPreset | None:
    """Look up a preset by *name*, returning ``None`` if not found."""
    return PRESETS.get(name)
