"""Groq LLM provider for Patter's pipeline mode.

Groq's Chat Completions API is OpenAI-compatible, so this provider is a
thin wrapper around :class:`getpatter.services.llm_loop.OpenAILLMProvider`
that points at ``https://api.groq.com/openai/v1``. All sampling kwargs
(``response_format``, ``parallel_tool_calls``, ``tool_choice``, ``seed``,
``top_p``, ``frequency_penalty``, ``presence_penalty``, ``stop``,
``temperature``, ``max_tokens``) are inherited from the parent and
forwarded to ``chat.completions.create`` automatically.
"""

from __future__ import annotations

import logging
import os
from enum import StrEnum
from typing import ClassVar

from getpatter.services.llm_loop import OpenAILLMProvider

__all__ = ["GroqLLMProvider", "GroqModel"]

logger = logging.getLogger("getpatter.providers.groq_llm")


class GroqModel(StrEnum):
    """Known Groq Chat Completions models. Availability depends on account tier."""

    LLAMA_3_3_70B_VERSATILE = "llama-3.3-70b-versatile"
    LLAMA_3_1_8B_INSTANT = "llama-3.1-8b-instant"
    LLAMA_3_3_70B_SPECDEC = "llama-3.3-70b-specdec"
    LLAMA_3_70B = "llama3-70b-8192"
    LLAMA_3_8B = "llama3-8b-8192"
    MIXTRAL_8X7B = "mixtral-8x7b-32768"
    GEMMA2_9B = "gemma2-9b-it"


_GROQ_BASE_URL = "https://api.groq.com/openai/v1"
_DEFAULT_MODEL = GroqModel.LLAMA_3_3_70B_VERSATILE.value


class GroqLLMProvider(OpenAILLMProvider):
    """LLM provider backed by Groq's OpenAI-compatible Chat Completions API.

    Streams in the same ``{"type": "text" | "tool_call" | "done"}`` chunk
    format as :class:`OpenAILLMProvider`. All OpenAI-spec sampling kwargs
    accepted by the parent (``response_format``, ``parallel_tool_calls``,
    ``tool_choice``, ``seed``, ``top_p``, ``frequency_penalty``,
    ``presence_penalty``, ``stop``, ``temperature``, ``max_tokens``) are
    forwarded transparently — see :class:`OpenAILLMProvider` for details.

    Args:
        api_key: Groq API key. If omitted, ``GROQ_API_KEY`` is read from
            the environment.
        model: Groq chat model ID. Defaults to ``llama-3.3-70b-versatile``.
        base_url: Optional Groq base URL override.
        **kwargs: Sampling kwargs forwarded to
            :class:`OpenAILLMProvider`.
    """

    #: Stable pricing/dashboard key — read by stream-handler/metrics.
    provider_key: ClassVar[str] = "groq"

    def __init__(
        self,
        api_key: str | None = None,
        model: GroqModel | str = _DEFAULT_MODEL,
        base_url: str = _GROQ_BASE_URL,
        **kwargs,
    ) -> None:
        try:
            from openai import AsyncOpenAI
        except ImportError as e:
            raise RuntimeError(
                "The 'openai' package is required for GroqLLMProvider. "
                "Install it with: pip install 'getpatter[groq]'"
            ) from e

        resolved_key = api_key or os.environ.get("GROQ_API_KEY")
        if not resolved_key:
            raise ValueError(
                "Groq API key is required, either as the 'api_key' argument "
                "or via the GROQ_API_KEY environment variable."
            )

        # Initialise parent state (model, sampling kwargs, _user_agent)
        # without using its OpenAI-pointed client. We swap in a Groq-pointed
        # client below using the same User-Agent the parent computed.
        super().__init__(api_key=resolved_key, model=model, **kwargs)
        self._client = AsyncOpenAI(
            api_key=resolved_key,
            base_url=base_url,
            default_headers={"User-Agent": self._user_agent},
        )

    def _record_completion_cost(
        self, *, prompt_tokens: int, completion_tokens: int
    ) -> None:
        """Stamp ``patter.cost.llm_*_tokens`` with the Groq provider tag."""
        try:
            from getpatter.observability.attributes import record_patter_attrs

            record_patter_attrs(
                {
                    "patter.cost.llm_input_tokens": prompt_tokens,
                    "patter.cost.llm_output_tokens": completion_tokens,
                    "patter.llm.provider": "groq",
                }
            )
        except Exception:  # pragma: no cover — defense in depth
            logger.debug("_record_completion_cost failed", exc_info=True)
