"""Heartbeat request/response models."""

from __future__ import annotations

from dataclasses import dataclass, field
from datetime import UTC, datetime
from typing import Any


@dataclass
class HeartbeatRequest:
    """
    Heartbeat sent to the server.

    Contains agent status and optional metrics summary.
    """

    agent_id: str
    timestamp: datetime = field(default_factory=lambda: datetime.now(UTC))
    state: str = "running"
    uptime_seconds: float = 0.0
    version: str = "0.1.0"
    metrics_summary: dict[str, Any] = field(default_factory=dict)
    system_info: dict[str, Any] = field(default_factory=dict)
    tags: dict[str, str] = field(default_factory=dict)

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary for API."""
        return {
            "agent_id": self.agent_id,
            "timestamp": self.timestamp.isoformat(),
            "state": self.state,
            "uptime_seconds": self.uptime_seconds,
            "version": self.version,
            "metrics_summary": self.metrics_summary,
            "system_info": self.system_info,
            "tags": self.tags,
        }


@dataclass
class HeartbeatResponse:
    """
    Response from server to heartbeat.

    May include configuration updates or pending commands.
    """

    acknowledged: bool
    server_time: datetime | None = None
    config_version: str | None = None
    config_update: dict[str, Any] | None = None
    pending_commands: int = 0
    messages: list[str] = field(default_factory=list)

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> HeartbeatResponse:
        """Create from dictionary."""
        server_time = data.get("server_time")
        if isinstance(server_time, str):
            server_time = datetime.fromisoformat(server_time)

        return cls(
            acknowledged=data.get("acknowledged", True),
            server_time=server_time,
            config_version=data.get("config_version"),
            config_update=data.get("config_update"),
            pending_commands=data.get("pending_commands", 0),
            messages=data.get("messages", []),
        )


@dataclass
class HealthStatus:
    """
    Aggregated health status for the agent.

    Used in heartbeat to report overall agent health.
    """

    healthy: bool
    state: str
    components: dict[str, ComponentHealth] = field(default_factory=dict)
    last_check: datetime = field(default_factory=lambda: datetime.now(UTC))

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary."""
        return {
            "healthy": self.healthy,
            "state": self.state,
            "components": {name: comp.to_dict() for name, comp in self.components.items()},
            "last_check": self.last_check.isoformat(),
        }


@dataclass
class ComponentHealth:
    """Health status of an individual component."""

    name: str
    healthy: bool
    message: str | None = None
    last_check: datetime = field(default_factory=lambda: datetime.now(UTC))
    details: dict[str, Any] = field(default_factory=dict)

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary."""
        return {
            "name": self.name,
            "healthy": self.healthy,
            "message": self.message,
            "last_check": self.last_check.isoformat(),
            "details": self.details,
        }
