"""
AWS Lex V2 Runtime Connector.

Uses boto3's ``lexv2-runtime`` client to call ``recognize_text``.
boto3 is an **optional** dependency — the import is guarded so that
PenBot works without it; a clear error is raised only when someone
actually tries to instantiate the connector.
"""

import os
from datetime import UTC, datetime
from typing import Any

from src.connectors.base import BaseConnector
from src.utils.helpers import generate_uuid
from src.utils.logging import get_logger

logger = get_logger(__name__)

try:
    import boto3
    from botocore.exceptions import BotoCoreError, ClientError

    _HAS_BOTO3 = True
except ImportError:
    _HAS_BOTO3 = False


class LexConnector(BaseConnector):
    """
    Connector for Amazon Lex V2 via the ``recognize_text`` API.

    Required config fields (under ``connection``):
        bot_id          – Lex bot identifier
        bot_alias_id    – Alias (e.g. ``TSTALIASID`` for the test alias)
        locale_id       – Locale, default ``en_US``

    AWS credentials are resolved through the standard boto3 chain:
        env vars  →  ~/.aws/credentials  →  IAM role
    """

    def __init__(self, config: dict[str, Any]):
        if not _HAS_BOTO3:
            raise ImportError(
                "boto3 is required for the AWS Lex connector. "
                "Install it with:  pip install boto3"
            )
        super().__init__(config)

        conn = self.connection_config
        self.bot_id = conn.get("bot_id", "")
        self.bot_alias_id = conn.get("bot_alias_id", "")
        self.locale_id = conn.get("locale_id", "en_US")
        self.region = conn.get("region", os.getenv("AWS_DEFAULT_REGION", "us-east-1"))

        if not self.bot_id or not self.bot_alias_id:
            raise ValueError(
                "AWS Lex connector requires 'bot_id' and 'bot_alias_id' "
                "in the connection config."
            )

        self.session_id = generate_uuid()
        self._client = None

    # ------------------------------------------------------------------
    # Lifecycle
    # ------------------------------------------------------------------

    async def initialize(self) -> None:
        """Create the boto3 Lex Runtime V2 client."""
        self._client = boto3.client(
            "lexv2-runtime",
            region_name=self.region,
        )
        logger.info(
            "lex_initialized",
            bot_id=self.bot_id,
            alias=self.bot_alias_id,
            region=self.region,
        )

    async def close(self) -> None:
        """No persistent connection to tear down."""
        self._client = None

    # ------------------------------------------------------------------
    # Core messaging
    # ------------------------------------------------------------------

    async def send_message(
        self,
        message: str,
        context: dict | None = None,
        image_data: str | None = None,
        image_mime_type: str | None = None,
    ) -> dict[str, Any]:
        """
        Send text to the Lex bot via ``recognize_text`` and return the
        concatenated response messages.
        """
        if self._client is None:
            await self.initialize()

        start = datetime.now(UTC)

        try:
            response = self._client.recognize_text(
                botId=self.bot_id,
                botAliasId=self.bot_alias_id,
                localeId=self.locale_id,
                sessionId=self.session_id,
                text=message,
            )
        except (ClientError, BotoCoreError) as exc:
            logger.error("lex_api_error", error=str(exc))
            return {
                "content": f"[Lex API Error: {exc}]",
                "timestamp": datetime.now(UTC),
                "metadata": {"error": True},
            }

        messages = response.get("messages", [])
        bot_text = " ".join(m.get("content", "") for m in messages).strip()
        if not bot_text:
            bot_text = "[Empty Lex response]"

        latency_ms = (datetime.now(UTC) - start).total_seconds() * 1000

        return {
            "content": bot_text,
            "timestamp": datetime.now(UTC),
            "metadata": {
                "session_id": self.session_id,
                "intent": response.get("sessionState", {}).get("intent", {}).get("name"),
                "dialog_action": response.get("sessionState", {})
                .get("dialogAction", {})
                .get("type"),
                "latency_ms": latency_ms,
                "raw_response": response,
            },
        }

    # ------------------------------------------------------------------
    # Session management
    # ------------------------------------------------------------------

    def reset_session(self) -> None:
        """Start a fresh Lex session (new session_id)."""
        self.session_id = generate_uuid()
        logger.info("lex_session_reset", session_id=self.session_id)

    # ------------------------------------------------------------------
    # Health check
    # ------------------------------------------------------------------

    async def health_check(self) -> bool:
        """Verify connectivity by sending a short greeting."""
        try:
            result = await self.send_message("Hi")
            return "error" not in result.get("metadata", {})
        except Exception:
            return False
