"""Server-side catalog of global item type definitions and defaults."""

from __future__ import annotations

from dataclasses import dataclass
from typing import TypeAlias, cast

from .items.registry import ITEM_MODULES, ITEM_TYPE_ORDER

ItemType: TypeAlias = str
ITEM_TYPE_SEQUENCE: tuple[ItemType, ...] = cast(tuple[ItemType, ...], ITEM_TYPE_ORDER)
ITEM_TYPE_LABELS: dict[ItemType, str] = {item_type: ITEM_MODULES[item_type].LABEL for item_type in ITEM_TYPE_SEQUENCE}
ITEM_TYPE_EDITABLE_PROPERTIES: dict[ItemType, tuple[str, ...]] = {
    item_type: ITEM_MODULES[item_type].EDITABLE_PROPERTIES for item_type in ITEM_TYPE_SEQUENCE
}

CLOCK_DEFAULT_TIME_ZONE = cast(str, ITEM_MODULES["clock"].DEFAULT_TIME_ZONE)
CLOCK_TIME_ZONE_OPTIONS = cast(tuple[str, ...], ITEM_MODULES["clock"].TIME_ZONE_OPTIONS)
RADIO_EFFECT_OPTIONS = cast(tuple[str, ...], ITEM_MODULES["radio_station"].EFFECT_OPTIONS)
RADIO_CHANNEL_OPTIONS = cast(tuple[str, ...], ITEM_MODULES["radio_station"].CHANNEL_OPTIONS)
PIANO_INSTRUMENT_OPTIONS = cast(tuple[str, ...], ITEM_MODULES["piano"].INSTRUMENT_OPTIONS)
PIANO_VOICE_MODE_OPTIONS = cast(tuple[str, ...], ITEM_MODULES["piano"].VOICE_MODE_OPTIONS)


@dataclass(frozen=True)
class ItemDefinition:
    """Global behavior and defaults shared by all instances of one item type."""

    default_title: str
    capabilities: tuple[str, ...]
    use_sound: str | None
    emit_sound: str | None
    default_params: dict
    use_cooldown_ms: int = 1000
    emit_range: int = 15
    directional: bool = False


def _build_definition(
    *,
    default_title: str,
    capabilities: tuple[str, ...],
    use_sound: str | None,
    emit_sound: str | None,
    default_params: dict,
    use_cooldown_ms: int,
    emit_range: int,
    directional: bool,
) -> ItemDefinition:
    """Build one immutable catalog definition from an item module."""

    return ItemDefinition(
        default_title=default_title,
        capabilities=capabilities,
        use_sound=use_sound,
        emit_sound=emit_sound,
        default_params=default_params,
        use_cooldown_ms=use_cooldown_ms,
        emit_range=emit_range,
        directional=directional,
    )


ITEM_DEFINITIONS: dict[ItemType, ItemDefinition] = {
    item_type: _build_definition(
        default_title=ITEM_MODULES[item_type].DEFAULT_TITLE,
        capabilities=ITEM_MODULES[item_type].CAPABILITIES,
        use_sound=ITEM_MODULES[item_type].USE_SOUND,
        emit_sound=ITEM_MODULES[item_type].EMIT_SOUND,
        default_params=ITEM_MODULES[item_type].DEFAULT_PARAMS,
        use_cooldown_ms=ITEM_MODULES[item_type].USE_COOLDOWN_MS,
        emit_range=ITEM_MODULES[item_type].EMIT_RANGE,
        directional=ITEM_MODULES[item_type].DIRECTIONAL,
    )
    for item_type in ITEM_TYPE_SEQUENCE
}

ITEM_TYPE_TOOLTIPS: dict[ItemType, str] = {
    item_type: ITEM_MODULES[item_type].TOOLTIP for item_type in ITEM_TYPE_SEQUENCE
}

GLOBAL_ITEM_PROPERTY_METADATA: dict[str, dict[str, object]] = {
    "type": {"valueType": "text", "tooltip": "Item type id for this object.", "label": "Type"},
    "x": {"valueType": "number", "tooltip": "Item X coordinate on the grid.", "label": "X"},
    "y": {"valueType": "number", "tooltip": "Item Y coordinate on the grid.", "label": "Y"},
    "carrierId": {"valueType": "text", "tooltip": "User id currently carrying this item, or none.", "label": "Carrier"},
    "version": {"valueType": "number", "tooltip": "Server-side item version incremented on each update.", "label": "Version"},
    "createdBy": {"valueType": "text", "tooltip": "Display name of the user who originally created this item.", "label": "Created by"},
    "updatedBy": {"valueType": "text", "tooltip": "Display name of the user who most recently updated this item.", "label": "Updated by"},
    "createdAt": {"valueType": "text", "tooltip": "Creation timestamp for this item.", "label": "Created at"},
    "updatedAt": {"valueType": "text", "tooltip": "Last update timestamp for this item.", "label": "Updated at"},
    "capabilities": {"valueType": "text", "tooltip": "Supported actions for this item type.", "label": "Capabilities"},
    "useSound": {
        "valueType": "sound",
        "tooltip": "One-shot sound played when this item is used successfully.",
        "maxLength": 2048,
    },
    "emitSound": {
        "valueType": "sound",
        "tooltip": "Looping sound emitted from this item on the grid.",
        "maxLength": 2048,
    },
    "useCooldownMs": {"valueType": "number", "tooltip": "Global cooldown in milliseconds between uses for this item type."},
    "emitRange": {"valueType": "number", "tooltip": "Maximum distance in squares where emitted audio can be heard."},
    "directional": {"valueType": "boolean", "tooltip": "Whether emitted audio favors the item's facing direction."},
    "emitSoundSpeed": {
        "valueType": "number",
        "tooltip": "Global emitted sound speed/pitch percent. 50 is normal.",
        "range": {"min": 0, "max": 100, "step": 0.1},
    },
    "emitSoundTempo": {
        "valueType": "number",
        "tooltip": "Global emitted sound tempo percent. 50 is normal.",
        "range": {"min": 0, "max": 100, "step": 0.1},
    },
    "emitInitialDelay": {
        "valueType": "number",
        "tooltip": "Delay in seconds before emitted audio starts after this sound is enabled.",
        "range": {"min": 0, "max": 300, "step": 0.1},
    },
    "emitLoopDelay": {
        "valueType": "number",
        "tooltip": "Delay in seconds between each emitted playback.",
        "range": {"min": 0, "max": 300, "step": 0.1},
    },
}

ITEM_TYPE_PROPERTY_METADATA: dict[ItemType, dict[str, dict[str, object]]] = {
    item_type: {**GLOBAL_ITEM_PROPERTY_METADATA, **ITEM_MODULES[item_type].PROPERTY_METADATA} for item_type in ITEM_TYPE_SEQUENCE
}


def get_item_definition(item_type: ItemType) -> ItemDefinition:
    """Return catalog definition for a known item type."""

    return ITEM_DEFINITIONS[item_type]


def is_known_item_type(item_type: str) -> bool:
    """Return whether a string item type id exists in discovered plugins."""

    return item_type in ITEM_DEFINITIONS


def get_item_use_cooldown_ms(item_type: ItemType) -> int:
    """Return validated global use cooldown in milliseconds for an item type."""

    definition = get_item_definition(item_type)
    cooldown_ms = definition.use_cooldown_ms
    if isinstance(cooldown_ms, int) and cooldown_ms > 0:
        return cooldown_ms
    return 1000


def get_item_global_properties(item_type: ItemType) -> dict[str, str | int | bool]:
    """Return non-editable global properties exposed in UI metadata."""

    definition = get_item_definition(item_type)
    return {
        "useSound": definition.use_sound or "none",
        "emitSound": definition.emit_sound or "none",
        "useCooldownMs": get_item_use_cooldown_ms(item_type),
        "emitRange": definition.emit_range if isinstance(definition.emit_range, int) and definition.emit_range > 0 else 15,
        "directional": bool(definition.directional),
        "emitSoundSpeed": 50,
        "emitSoundTempo": 50,
        "emitInitialDelay": 0,
        "emitLoopDelay": 0,
    }
