"""
System Context Type.

Represents system prompts, instructions, and agent personas.
"""

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

from .base import BaseContext, ContextPriority, ContextType


@dataclass(eq=False)
class SystemContext(BaseContext):
    """
    Context for system prompts and instructions.

    System context typically includes:
    - Agent persona and role definitions
    - Behavioral instructions
    - Safety guidelines
    - Output format requirements

    System context is usually high priority and should
    rarely be truncated or omitted.
    """

    # System context specific fields
    role: str = field(default="assistant")
    instructions_type: str = field(default="general")

    def __post_init__(self) -> None:
        """Set high priority for system context."""
        # System context defaults to high priority
        if self.priority == ContextPriority.NORMAL.value:
            self.priority = ContextPriority.HIGH.value

    def get_type(self) -> ContextType:
        """Return SYSTEM context type."""
        return ContextType.SYSTEM

    def to_dict(self) -> dict[str, Any]:
        """Convert to dictionary with system-specific fields."""
        base = super().to_dict()
        base.update(
            {
                "role": self.role,
                "instructions_type": self.instructions_type,
            }
        )
        return base

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> "SystemContext":
        """Create SystemContext from dictionary."""
        return cls(
            id=data.get("id", ""),
            content=data["content"],
            source=data["source"],
            timestamp=datetime.fromisoformat(data["timestamp"])
            if isinstance(data.get("timestamp"), str)
            else data.get("timestamp", datetime.now(UTC)),
            priority=data.get("priority", ContextPriority.HIGH.value),
            metadata=data.get("metadata", {}),
            role=data.get("role", "assistant"),
            instructions_type=data.get("instructions_type", "general"),
        )

    @classmethod
    def create_persona(
        cls,
        name: str,
        description: str,
        capabilities: list[str] | None = None,
        constraints: list[str] | None = None,
    ) -> "SystemContext":
        """
        Create a persona system context.

        Args:
            name: Agent name/role
            description: Role description
            capabilities: List of things the agent can do
            constraints: List of limitations

        Returns:
            SystemContext with formatted persona
        """
        parts = [f"You are {name}.", "", description]

        if capabilities:
            parts.append("")
            parts.append("You can:")
            for cap in capabilities:
                parts.append(f"- {cap}")

        if constraints:
            parts.append("")
            parts.append("You must not:")
            for constraint in constraints:
                parts.append(f"- {constraint}")

        return cls(
            content="\n".join(parts),
            source="persona_builder",
            role=name.lower().replace(" ", "_"),
            instructions_type="persona",
            priority=ContextPriority.HIGHEST.value,
        )

    @classmethod
    def create_instructions(
        cls,
        instructions: str | list[str],
        source: str = "instructions",
    ) -> "SystemContext":
        """
        Create an instructions system context.

        Args:
            instructions: Instructions string or list of instruction strings
            source: Source identifier

        Returns:
            SystemContext with instructions
        """
        if isinstance(instructions, list):
            content = "\n".join(f"- {inst}" for inst in instructions)
        else:
            content = instructions

        return cls(
            content=content,
            source=source,
            instructions_type="instructions",
            priority=ContextPriority.HIGH.value,
        )
