"""Langfuse-backed prompt provider."""

from __future__ import annotations

from typing import Any, Callable

from dr_langfuse.client import (
    LangfuseConfig,
    default_langfuse_client_factory,
    resolve_client,
)
from dr_langfuse.errors.codes import ErrorCode
from dr_langfuse.errors.error_envelope import ErrorEnvelope
from dr_langfuse.errors.langfuse_error import LangfuseError
from dr_langfuse.prompts.prompt_fetch_request import PromptFetchRequest
from dr_langfuse.prompts.prompt_payload import PromptPayload


class LangfusePromptProvider:
    """Prompt provider implementation backed by Langfuse."""

    def __init__(
        self,
        *,
        config: LangfuseConfig | None = None,
        client: Any | None = None,
        client_factory: Callable[[LangfuseConfig], Any] | None = None,
    ) -> None:
        self._config = config or LangfuseConfig.from_env()
        self._client_factory = client_factory or default_langfuse_client_factory
        self._client_resolution = resolve_client(
            client=client,
            config=self._config,
            client_factory=self._client_factory,
        )

    def fetch_prompt(self, request: PromptFetchRequest) -> PromptPayload:
        if self._client_resolution.init_error is not None:
            raise LangfuseError(self._client_resolution.init_error)

        client = self._client_resolution.client
        if client is None:
            raise LangfuseError(
                ErrorEnvelope(
                    code=ErrorCode.INTERNAL_ERROR,
                    message="Langfuse client resolution failed: client is None",
                    retriable=False,
                    details={"operation": "fetch_prompt"},
                )
            )

        try:
            prompt = client.get_prompt(
                request.prompt_name,
                label=request.label,
                version=request.version,
            )
            return PromptPayload(prompt=prompt, request=request)
        except LangfuseError:
            raise
        except Exception as exc:
            raise LangfuseError(
                ErrorEnvelope(exception=exc, operation="fetch_prompt")
            ) from exc
