from __future__ import annotations

import os
from typing import Mapping, Optional

import httpx

from ._base_client import AsyncAPIClient, SyncAPIClient
from ._compat import cached_property
from ._constants import DEFAULT_BASE_URL, DEFAULT_MAX_RETRIES, DEFAULT_TIMEOUT
from ._exceptions import PonyFlashError
from ._types import NotGiven, NOT_GIVEN
from ._version import __version__

__all__ = ["PonyFlash", "AsyncPonyFlash"]


class PonyFlash(SyncAPIClient):
    files: Files
    images: Images
    video: Video
    speech: Speech
    music: Music
    models: Models
    generations: Generations
    account: Account

    def __init__(
        self,
        *,
        api_key: str | None = None,
        base_url: str | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
        max_retries: int = DEFAULT_MAX_RETRIES,
        default_headers: Mapping[str, str] | None = None,
        http_client: httpx.Client | None = None,
    ) -> None:
        if api_key is None:
            api_key = os.environ.get("PONYFLASH_API_KEY")
        if api_key is None:
            raise PonyFlashError(
                "api_key must be provided or set as PONYFLASH_API_KEY environment variable"
            )

        if base_url is None:
            base_url = os.environ.get("PONYFLASH_BASE_URL", DEFAULT_BASE_URL)

        if isinstance(timeout, NotGiven):
            _timeout = DEFAULT_TIMEOUT
        elif isinstance(timeout, (int, float)):
            _timeout = httpx.Timeout(timeout)
        elif timeout is None:
            _timeout = httpx.Timeout(None)
        else:
            _timeout = timeout

        super().__init__(
            base_url=base_url,
            api_key=api_key,
            max_retries=max_retries,
            timeout=_timeout,
            http_client=http_client,
            custom_headers=default_headers,
        )

    @cached_property
    def files(self) -> Files:  # type: ignore[override]
        from .resources.files import Files
        return Files(self)

    @cached_property
    def images(self) -> Images:  # type: ignore[override]
        from .resources.images import Images
        return Images(self)

    @cached_property
    def video(self) -> Video:  # type: ignore[override]
        from .resources.video import Video
        return Video(self)

    @cached_property
    def speech(self) -> Speech:  # type: ignore[override]
        from .resources.speech import Speech
        return Speech(self)

    @cached_property
    def music(self) -> Music:  # type: ignore[override]
        from .resources.music import Music
        return Music(self)

    @cached_property
    def models(self) -> Models:  # type: ignore[override]
        from .resources.models import Models
        return Models(self)

    @cached_property
    def generations(self) -> Generations:  # type: ignore[override]
        from .resources.generations import Generations
        return Generations(self)

    @cached_property
    def account(self) -> Account:  # type: ignore[override]
        from .resources.account import Account
        return Account(self)


class AsyncPonyFlash(AsyncAPIClient):
    files: AsyncFiles
    images: AsyncImages
    video: AsyncVideo
    speech: AsyncSpeech
    music: AsyncMusic
    models: AsyncModels
    generations: AsyncGenerations
    account: AsyncAccount

    def __init__(
        self,
        *,
        api_key: str | None = None,
        base_url: str | None = None,
        timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
        max_retries: int = DEFAULT_MAX_RETRIES,
        default_headers: Mapping[str, str] | None = None,
        http_client: httpx.AsyncClient | None = None,
    ) -> None:
        if api_key is None:
            api_key = os.environ.get("PONYFLASH_API_KEY")
        if api_key is None:
            raise PonyFlashError(
                "api_key must be provided or set as PONYFLASH_API_KEY environment variable"
            )

        if base_url is None:
            base_url = os.environ.get("PONYFLASH_BASE_URL", DEFAULT_BASE_URL)

        if isinstance(timeout, NotGiven):
            _timeout = DEFAULT_TIMEOUT
        elif isinstance(timeout, (int, float)):
            _timeout = httpx.Timeout(timeout)
        elif timeout is None:
            _timeout = httpx.Timeout(None)
        else:
            _timeout = timeout

        super().__init__(
            base_url=base_url,
            api_key=api_key,
            max_retries=max_retries,
            timeout=_timeout,
            http_client=http_client,
            custom_headers=default_headers,
        )

    @cached_property
    def files(self) -> AsyncFiles:  # type: ignore[override]
        from .resources.files import AsyncFiles
        return AsyncFiles(self)

    @cached_property
    def images(self) -> AsyncImages:  # type: ignore[override]
        from .resources.images import AsyncImages
        return AsyncImages(self)

    @cached_property
    def video(self) -> AsyncVideo:  # type: ignore[override]
        from .resources.video import AsyncVideo
        return AsyncVideo(self)

    @cached_property
    def speech(self) -> AsyncSpeech:  # type: ignore[override]
        from .resources.speech import AsyncSpeech
        return AsyncSpeech(self)

    @cached_property
    def music(self) -> AsyncMusic:  # type: ignore[override]
        from .resources.music import AsyncMusic
        return AsyncMusic(self)

    @cached_property
    def models(self) -> AsyncModels:  # type: ignore[override]
        from .resources.models import AsyncModels
        return AsyncModels(self)

    @cached_property
    def generations(self) -> AsyncGenerations:  # type: ignore[override]
        from .resources.generations import AsyncGenerations
        return AsyncGenerations(self)

    @cached_property
    def account(self) -> AsyncAccount:  # type: ignore[override]
        from .resources.account import AsyncAccount
        return AsyncAccount(self)


# TYPE_CHECKING imports for forward-reference annotations
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from .resources.files import AsyncFiles, Files
    from .resources.images import AsyncImages, Images
    from .resources.video import AsyncVideo, Video
    from .resources.speech import AsyncSpeech, Speech
    from .resources.music import AsyncMusic, Music
    from .resources.models import AsyncModels, Models
    from .resources.generations import AsyncGenerations, Generations
    from .resources.account import Account, AsyncAccount
