"""System status domain models and enums."""

from __future__ import annotations

from enum import IntEnum

from pydantic import BaseModel, ConfigDict

from radiens_core.models.ports import GPIOChannelCount, Port, PortChannelCount

# ===================================================================
# System status enums
# ===================================================================


class BackboneMode(IntEnum):
    """Hardware backbone mode. Values match proto ``allego.BackboneMode``."""

    SMARTBOX_PRO = 0
    SMARTBOX_SIM_GEN_SINE = 1  # low freq
    SMARTBOX_SIM_GEN_SPIKES = 2
    SMARTBOX_SIM_DATASOURCE = 3
    OPEN_EPHYS_USB3 = 4
    INTAN_RECORDING_CONTROLLER_1024 = 5
    SMARTBOX_CLASSIC = 6
    INTAN_RECORDING_CONTROLLER_512 = 7
    OPEN_EPHYS_USB2 = 8
    INTAN_USB2 = 9
    SMARTBOX_SIM_GEN_SINE_MAPPED = 10
    SMARTBOX_SIM_GEN_SINE_HIGH_FREQ = 11
    SMARTBOX_SIM_GEN_SINE_MULTI_BAND = 12
    SMARTBOX_PRO_SINAPS_256 = 13
    SMARTBOX_PRO_SINAPS_1024 = 14
    XDAQ_ONE_REC = 15
    XDAQ_ONE_STIM = 16
    XDAQ_CORE_REC = 17
    XDAQ_CORE_STIM = 18
    SMARTBOX_PRO_SINAPS_512 = 19
    XDAQ_GEN2_ONE_STIM = 20
    XDAQ_GEN2_CORE_STIM = 21
    XDAQ_GEN2_ONE_REC = 22
    XDAQ_GEN2_CORE_REC = 23
    SMARTBOX_SIM_GEN_LFP = 24


class StreamMode(IntEnum):
    """Data stream mode. Values match proto ``allego.StreamMode``."""

    OFF = 0  # S_OFF
    ON = 1  # S_ON


class RecordMode(IntEnum):
    """Data recording mode. Values match proto ``allego.RecordMode``."""

    OFF = 0  # R_OFF
    ON = 1  # R_ON


class DataRecordingType(IntEnum):
    """Data recording type. Values match proto ``allego.DataRecordingType``."""

    CONTINUOUS = 0  # continuous
    SPIKES = 1  # spikes
    CONTINUOUS_AND_SPIKES = 2  # continuousAndSpikes


# ===================================================================
# Status models
# ===================================================================


class RestartRequest(BaseModel):
    """Request to restart the system with a specific backbone mode."""

    model_config = ConfigDict(frozen=True)

    mode: BackboneMode


class RecordStateRequest(BaseModel):
    """Request to change recording state."""

    model_config = ConfigDict(frozen=True)

    mode: RecordMode
    port: Port | None = None  # If None, system-level record control


class StreamStateRequest(BaseModel):
    """Request to change streaming state."""

    model_config = ConfigDict(frozen=True)

    mode: StreamMode


class StreamingStatus(BaseModel):
    """Current streaming status."""

    model_config = ConfigDict(frozen=True)

    stream_mode: StreamMode
    primary_cache_t_range: list[float]
    hardware_memory_level: float


class RecordingStatus(BaseModel):
    """Current recording status."""

    model_config = ConfigDict(frozen=True)

    record_mode: RecordMode
    active_filename: str
    duration: float
    error: str
    record_mode_port_a: RecordMode | None = None
    record_mode_port_b: RecordMode | None = None
    record_mode_port_c: RecordMode | None = None
    record_mode_port_d: RecordMode | None = None
    record_mode_port_e: RecordMode | None = None
    record_mode_port_f: RecordMode | None = None
    record_mode_port_g: RecordMode | None = None
    record_mode_port_h: RecordMode | None = None


class RecordingConfig(BaseModel):
    """Recording configuration settings.

    Configures output file paths, naming, and recording behavior.
    Used as both request (for set_recording_config) and response (for get_recording_config).
    """

    model_config = ConfigDict(frozen=True)

    base_file_name: str
    """Base filename for recording output (without extension or timestamp)."""

    base_file_path: str
    """Base directory path for recording files."""

    datasource_idx: int = 0
    """Index number for the composed file name."""

    time_stamp: bool = True
    """True to include timestamp in the composed file name."""

    split_files_by_port: bool = False
    """True to create separate files for each port."""

    force_start_at_tstamp_0: bool = False
    """True to force recording to start at timestamp 0."""

    recording_type: DataRecordingType = DataRecordingType.CONTINUOUS
    """Type of data to record (continuous, spikes, or both)."""


class BackboneStatus(BaseModel):
    """Complete system backbone status."""

    model_config = ConfigDict(frozen=True)

    streaming: StreamingStatus
    recording: RecordingStatus
    ports: list[PortChannelCount]
    is_connected: bool
    gpio_channel_count: GPIOChannelCount
