"""Base agent class -- shared infrastructure for all Hive agents.

Every Hive agent inherits from BaseAgent, which provides:
- Message passing (structured AgentMessage protocol)
- Scope boundary enforcement
- Configuration loading from .hive/config.yaml
- Memory read/write access
- Logging and activity tracking
"""

from __future__ import annotations

import logging
from dataclasses import dataclass, field
from datetime import datetime, timezone
from enum import Enum
from pathlib import Path  # noqa: TC003 -- used at runtime
from typing import Any

logger = logging.getLogger("hive")


class AgentRole(str, Enum):
    """Enumeration of agent roles in the Hive system."""

    CEO = "ceo"
    ANALYST = "analyst"
    WATCHER = "watcher"
    BUILDER = "builder"
    ADVISOR = "advisor"


class MessageType(str, Enum):
    """Types of inter-agent messages."""

    TASK = "task"
    RESULT = "result"
    ALERT = "alert"
    QUERY = "query"
    SIGNAL = "signal"


class Priority(str, Enum):
    """Message and task priority levels."""

    CRITICAL = "critical"
    HIGH = "high"
    NORMAL = "normal"
    LOW = "low"


@dataclass
class AgentMessage:
    """Structured message for inter-agent communication.

    All agent communication routes through Hive CEO (hub-and-spoke model).
    Exception: Watcher → Builder fast path for Level 0-1 health fixes.
    """

    from_agent: AgentRole
    to_agent: AgentRole
    message_type: MessageType
    priority: Priority
    payload: dict[str, Any]
    context: dict[str, Any] = field(default_factory=dict)
    timestamp: datetime = field(default_factory=lambda: datetime.now(timezone.utc))
    session_id: str = ""


class BaseAgent:
    """Base class for all Hive agents.

    Provides shared infrastructure while enforcing scope boundaries.
    Each agent subclass defines its own capabilities and constraints.
    """

    role: AgentRole
    _workspace_root: Path
    _hive_dir: Path
    _enabled: bool

    def __init__(self, workspace_root: Path) -> None:
        self._workspace_root = workspace_root
        self._hive_dir = workspace_root / ".hive"
        self._enabled = True
        self._message_log: list[AgentMessage] = []

    @property
    def name(self) -> str:
        """Human-readable agent name."""
        return self.role.value.capitalize()

    @property
    def hive_dir(self) -> Path:
        """Path to the .hive/ directory."""
        return self._hive_dir

    @property
    def memory_dir(self) -> Path:
        """Path to .hive/memory/ directory."""
        return self._hive_dir / "memory"

    @property
    def is_enabled(self) -> bool:
        """Whether this agent is currently active."""
        return self._enabled

    def enable(self) -> None:
        """Activate this agent."""
        self._enabled = True
        logger.info("Agent %s enabled", self.name)

    def disable(self) -> None:
        """Deactivate this agent."""
        self._enabled = False
        logger.info("Agent %s disabled", self.name)

    def send_message(self, message: AgentMessage) -> None:
        """Send a message (logged for audit trail)."""
        self._message_log.append(message)
        logger.debug(
            "Message from %s to %s: %s [%s]",
            message.from_agent.value,
            message.to_agent.value,
            message.message_type.value,
            message.priority.value,
        )

    def receive_message(self, message: AgentMessage) -> AgentMessage | None:
        """Process an incoming message. Override in subclasses.

        Returns a response message, or None if no response needed.
        """
        self._message_log.append(message)
        return None

    def read_memory(self, filename: str) -> str:
        """Read a file from .hive/memory/."""
        filepath = self.memory_dir / filename
        if filepath.exists():
            return filepath.read_text(encoding="utf-8")
        return ""

    def write_memory(self, filename: str, content: str) -> None:
        """Write to a file in .hive/memory/ (append mode)."""
        filepath = self.memory_dir / filename
        filepath.parent.mkdir(parents=True, exist_ok=True)
        with filepath.open("a", encoding="utf-8") as f:
            f.write(content)
        logger.debug("Memory written: %s (%d bytes)", filename, len(content))

    def read_identity(self) -> str:
        """Read .hive/identity.md."""
        identity_path = self._hive_dir / "identity.md"
        if identity_path.exists():
            return identity_path.read_text(encoding="utf-8")
        return ""

    def read_soul(self) -> str:
        """Read .hive/soul.md."""
        soul_path = self._hive_dir / "soul.md"
        if soul_path.exists():
            return soul_path.read_text(encoding="utf-8")
        return ""

    def read_constraints(self) -> str:
        """Read .hive/constraints.md."""
        constraints_path = self._hive_dir / "constraints.md"
        if constraints_path.exists():
            return constraints_path.read_text(encoding="utf-8")
        return ""

    def get_status(self) -> dict[str, Any]:
        """Get current agent status for dashboard display."""
        return {
            "role": self.role.value,
            "name": self.name,
            "enabled": self._enabled,
            "message_count": len(self._message_log),
        }
