"""Agent foundation for conversation integration."""

from __future__ import annotations

from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Any, Literal

from homeassistant.core import Context
from homeassistant.helpers import intent, llm

from .const import DOMAIN


@dataclass(frozen=True)
class AgentInfo:
    """Container for conversation agent info."""

    id: str
    name: str
    supports_streaming: bool


@dataclass(slots=True)
class ConversationInput:
    """User input to be processed."""

    text: str
    """User spoken text."""

    context: Context
    """Context of the request."""

    conversation_id: str | None
    """Unique identifier for the conversation."""

    device_id: str | None
    """Unique identifier for the device."""

    satellite_id: str | None
    """Unique identifier for the satellite."""

    language: str
    """Language of the request."""

    agent_id: str
    """Agent to use for processing."""

    extra_system_prompt: str | None = None
    """Extra prompt to provide extra info to LLMs how to understand the command."""

    def as_dict(self) -> dict[str, Any]:
        """Return input as a dict."""
        return {
            "text": self.text,
            "context": self.context.as_dict(),
            "conversation_id": self.conversation_id,
            "device_id": self.device_id,
            "satellite_id": self.satellite_id,
            "language": self.language,
            "agent_id": self.agent_id,
            "extra_system_prompt": self.extra_system_prompt,
        }

    def as_llm_context(self, conversing_domain: str) -> llm.LLMContext:
        """Return input as an LLM context."""
        return llm.LLMContext(
            platform=conversing_domain,
            context=self.context,
            language=self.language,
            assistant=DOMAIN,
            device_id=self.device_id,
        )


@dataclass(slots=True)
class ConversationResult:
    """Result of async_process."""

    response: intent.IntentResponse
    conversation_id: str | None = None
    continue_conversation: bool = False

    def as_dict(self) -> dict[str, Any]:
        """Return result as a dict."""
        return {
            "response": self.response.as_dict(),
            "conversation_id": self.conversation_id,
            "continue_conversation": self.continue_conversation,
        }


class AbstractConversationAgent(ABC):
    """Abstract conversation agent."""

    @property
    @abstractmethod
    def supported_languages(self) -> list[str] | Literal["*"]:
        """Return a list of supported languages."""

    @abstractmethod
    async def async_process(self, user_input: ConversationInput) -> ConversationResult:
        """Process a sentence."""

    async def async_reload(self, language: str | None = None) -> None:
        """Clear cached intents for a language."""

    async def async_prepare(self, language: str | None = None) -> None:
        """Load intents for a language."""
