from collections import deque

from bussdcc import Process, ContextProtocol, Event, Message

from .. import message


class SystemStatsProcess(Process):
    name = "system_stats"

    HISTORY_SECONDS = 300

    def start(self, ctx: ContextProtocol) -> None:
        self._net_history: dict[str, deque[dict[str, float | int]]] = {}
        self._cpu_history: deque[dict[str, float | int]] = deque()

    def handle_event(self, ctx: ContextProtocol, evt: Event[Message]) -> None:
        payload = evt.payload

        if isinstance(payload, message.CPUTemperatureUpdate):
            ctx.state.set("system.cpu.temperature", payload)
        elif isinstance(payload, message.MemoryUsageUpdate):
            ctx.state.set("system.memory.usage", payload)
        elif isinstance(payload, message.DiskUsageUpdate):
            ctx.state.set("system.disk.usage", payload)
        elif isinstance(payload, message.LoadAverageUpdate):
            ctx.state.set("system.load", payload)
        elif isinstance(payload, message.CPUUsageUpdate):
            ctx.state.set("system.cpu.usage", payload)

            if not evt.time:
                return

            now = evt.time.timestamp()

            self._cpu_history.append(
                {
                    "t": now,
                    "user": payload.user,
                    "system": payload.system,
                    "iowait": payload.iowait,
                    "idle": payload.idle,
                }
            )

            cutoff = now - self.HISTORY_SECONDS
            while self._cpu_history and self._cpu_history[0]["t"] < cutoff:
                self._cpu_history.popleft()

            ctx.state.set("system.cpu.history", list(self._cpu_history))

        elif isinstance(payload, message.NetworkUsageUpdate):
            ctx.state.set("system.network.usage", payload)

            if not evt.time:
                return

            now = evt.time.timestamp()

            for iface in payload.interfaces:
                name = iface.interface
                history = self._net_history.setdefault(name, deque())

                history.append(
                    {
                        "t": now,
                        "rx_bps": iface.rx_bps,
                        "tx_bps": iface.tx_bps,
                    }
                )

                cutoff = now - self.HISTORY_SECONDS
                while history and history[0]["t"] < cutoff:
                    history.popleft()

            ctx.state.set(
                "system.network.history",
                {k: list(v) for k, v in self._net_history.items()},
            )
