import re
import os
import openai
from openai import AsyncOpenAI

from .base import LLMProvider, ContextLengthExceededError, ProviderAuthError, ProviderConnectionError

class OpenAIProvider(LLMProvider):
    """LLM provider implementation for OpenAI models."""
    _client: AsyncOpenAI | None = None

    def _get_client(self) -> AsyncOpenAI:
        if OpenAIProvider._client is None:
            if not (api_key := os.environ.get('TELLMGRAMBOT_OPENAI_API_KEY')):
                raise ProviderAuthError("OpenAI API key not set. Provide TELLMGRAMBOT_OPENAI_API_KEY.")
            OpenAIProvider._client = AsyncOpenAI(api_key=api_key)
        return OpenAIProvider._client

    async def complete(self, model: str, messages: list[dict]) -> str:
        client = self._get_client()
        try:
            response = await client.chat.completions.create(
                model=model,
                messages=messages,
            )
            return response.choices[0].message.content
        except openai.AuthenticationError as e:
            raise ProviderAuthError(f"OpenAI authentication failed: {e}") from e
        except openai.BadRequestError as e:
            if re.search(r'maximum context.+reduce the length', str(e)):
                raise ContextLengthExceededError() from e
            raise
        except openai.APIConnectionError as e:
            raise ProviderConnectionError(f"OpenAI connection error: {e}") from e
