from typing import Optional, Generator
from ..client import _client
from ..config import get_profile, Profile


class BoundModule:
    def __init__(self, personality: str, profile: Profile):
        self._personality = personality
        self._profile = profile

    def ask(self, prompt: str, context: Optional[str] = None) -> str:
        result = _client.ask(self._personality, prompt, self._profile, context=context, stream=False)
        return result.get("response", "")

    def stream(self, prompt: str, context: Optional[str] = None) -> Generator[str, None, None]:
        yield from _client.ask(self._personality, prompt, self._profile, context=context, stream=True)

    def ask_with_meta(self, prompt: str, context: Optional[str] = None) -> dict:
        return _client.ask(self._personality, prompt, self._profile, context=context, stream=False)

    def quota(self) -> dict:
        return _client.quota(self._profile)


class BaseModule:
    _personality: str = "full"

    @classmethod
    def use(cls, profile_name: str) -> BoundModule:
        """
        Utilise un profil spécifique.

        Exemple::
            from candy import cfg, Coding
            cfg.A.lang  = "FR"
            cfg.A.style = "detailed"
            Coding.use("A").ask("Explique les générateurs")
        """
        return BoundModule(cls._personality, get_profile(profile_name))

    @classmethod
    def ask(cls, prompt: str, context: Optional[str] = None) -> str:
        """Utilise le profil 'default'."""
        result = _client.ask(cls._personality, prompt, get_profile("default"), context=context, stream=False)
        return result.get("response", "")

    @classmethod
    def stream(cls, prompt: str, context: Optional[str] = None) -> Generator[str, None, None]:
        """Stream avec le profil 'default'."""
        yield from _client.ask(cls._personality, prompt, get_profile("default"), context=context, stream=True)

    @classmethod
    def ask_with_meta(cls, prompt: str, context: Optional[str] = None) -> dict:
        return _client.ask(cls._personality, prompt, get_profile("default"), context=context, stream=False)

    @classmethod
    def quota(cls) -> dict:
        return _client.quota(get_profile("default"))
