from __future__ import annotations

import threading
from dataclasses import dataclass

from hytop.core.history import SlidingHistory


@dataclass
class Sample:
    """One parsed hy-smi sample for a single GPU.

    Attributes:
        ts: Monotonic timestamp when the sample was captured.
        temp_c: GPU core temperature in Celsius.
        avg_pwr_w: Average power draw in Watts.
        vram_pct: VRAM usage percentage.
        hcu_pct: HCU usage percentage.
        sclk_mhz: sclk frequency in MHz.
    """

    ts: float
    temp_c: float | None = None
    avg_pwr_w: float | None = None
    vram_pct: float | None = None
    hcu_pct: float | None = None
    sclk_mhz: float | None = None


@dataclass
class NodeResult:
    """Collection result for one host.

    Attributes:
        host: Host name used for collection.
        samples: Parsed samples keyed by GPU id.
        error: Error message when collection failed; otherwise None.
    """

    host: str
    samples: dict[int, Sample]
    error: str | None = None


@dataclass
class HostSnapshot:
    """Latest published collector output for a host.

    Attributes:
        seq: Monotonic sequence number incremented per publish.
        updated_ts: Monotonic timestamp when snapshot was updated.
        result: Latest node result from collector; None before first publish.
    """

    seq: int = 0
    updated_ts: float = 0.0
    result: NodeResult | None = None


@dataclass
class MonitorState:
    """In-memory monitor state shared by collectors and render loop.

    Attributes:
        max_window: Sliding window length in seconds.
        histories: Per host+gpu sliding histories.
        discovered_keys: Dynamically discovered host+gpu keys.
        last_applied_sample_ts: Last sample timestamp applied per host+gpu key.
        monitored_keys: Effective monitored keys after filtering/discovery.
        errors: Latest host-level collection errors.
        host_state: Latest collector snapshots per host.
        processed_seq: Last consumed snapshot sequence per host.
        state_lock: Lock protecting shared snapshot state.
        stop_event: Event signaling collector shutdown.
    """

    max_window: float
    histories: dict[tuple[str, int], SlidingHistory]
    discovered_keys: set[tuple[str, int]]
    last_applied_sample_ts: dict[tuple[str, int], float]
    monitored_keys: set[tuple[str, int]]
    errors: dict[str, str]
    host_state: dict[str, HostSnapshot]
    processed_seq: dict[str, int]
    state_lock: threading.Lock
    stop_event: threading.Event
