"""Canonical preprocess asset definitions shared by GUI and runtime orchestration."""

from __future__ import annotations

from dataclasses import dataclass

from python_app.models.run_config_model import PreprocessAssetModel, RunConfigModel


@dataclass(frozen=True, slots=True)
class PreprocessAssetSpec:
    """Stable description of one preprocess asset."""

    key: str
    display_name: str
    set_kind: str
    runtime_filename: str
    channel: str


PREPROCESS_ASSET_SPECS = {
    "s21_calibration": PreprocessAssetSpec(
        key="s21_calibration",
        display_name="S21 Calibration",
        set_kind="s21_calibration",
        runtime_filename="s21_calibration_bundle.bin",
        channel="s21",
    ),
    "s21_reference": PreprocessAssetSpec(
        key="s21_reference",
        display_name="S21 Reference",
        set_kind="s21_reference",
        runtime_filename="s21_reference_bundle.bin",
        channel="s21",
    ),
    "s11_open": PreprocessAssetSpec(
        key="s11_open",
        display_name="S11 Open",
        set_kind="s11_open",
        runtime_filename="s11_open_calibration_bundle.bin",
        channel="s11",
    ),
    "s11_short": PreprocessAssetSpec(
        key="s11_short",
        display_name="S11 Short",
        set_kind="s11_short",
        runtime_filename="s11_short_calibration_bundle.bin",
        channel="s11",
    ),
    "s11_load": PreprocessAssetSpec(
        key="s11_load",
        display_name="S11 Load",
        set_kind="s11_load",
        runtime_filename="s11_load_calibration_bundle.bin",
        channel="s11",
    ),
    "s11_reference": PreprocessAssetSpec(
        key="s11_reference",
        display_name="S11 Reference",
        set_kind="s11_reference",
        runtime_filename="s11_reference_bundle.bin",
        channel="s11",
    ),
}

PREPROCESS_ASSET_KEYS = tuple(PREPROCESS_ASSET_SPECS.keys())
S21_PREPROCESS_ASSET_KEYS = ("s21_calibration", "s21_reference")
S11_PREPROCESS_ASSET_KEYS = ("s11_open", "s11_short", "s11_load", "s11_reference")
S11_PREPROCESS_CALIBRATION_KEYS = ("s11_open", "s11_short", "s11_load")
VISIBLE_PREPROCESS_ASSET_KEYS = S21_PREPROCESS_ASSET_KEYS
REQUIRED_PREPROCESS_ASSET_KEYS = S21_PREPROCESS_ASSET_KEYS


def preprocess_asset_model(config: RunConfigModel, key: str) -> PreprocessAssetModel:
    """Return nested preprocess asset model by canonical asset key."""
    if key == "s21_calibration":
        return config.preprocess.s21.calibration
    if key == "s21_reference":
        return config.preprocess.s21.reference
    if key == "s11_open":
        return config.preprocess.s11.calibration.open
    if key == "s11_short":
        return config.preprocess.s11.calibration.short
    if key == "s11_load":
        return config.preprocess.s11.calibration.load
    if key == "s11_reference":
        return config.preprocess.s11.reference
    raise KeyError(f"Unknown preprocess asset key: {key}")


def preprocess_asset_display_name(key: str) -> str:
    """Return human-readable label for preprocess asset."""
    return PREPROCESS_ASSET_SPECS[key].display_name


def preprocess_asset_channel(key: str) -> str:
    """Return associated trace channel for preprocess asset."""
    return PREPROCESS_ASSET_SPECS[key].channel


def preprocess_asset_set_name(config: RunConfigModel, key: str) -> str:
    """Return normalized selected set name for one preprocess asset."""
    return str(preprocess_asset_model(config, key).set_name).strip()


def runtime_preprocess_asset_keys(config: RunConfigModel) -> tuple[str, ...]:
    """Return preprocess assets that should be exported and validated for runtime."""
    enabled_keys = list(REQUIRED_PREPROCESS_ASSET_KEYS)

    has_full_s11_calibration = all(
        preprocess_asset_set_name(config, key)
        for key in S11_PREPROCESS_CALIBRATION_KEYS
    )
    if not has_full_s11_calibration:
        return tuple(enabled_keys)

    enabled_keys.extend(S11_PREPROCESS_CALIBRATION_KEYS)
    if preprocess_asset_set_name(config, "s11_reference"):
        enabled_keys.append("s11_reference")
    return tuple(enabled_keys)
