"""The Appliku class — the user-facing SDK entry point."""

from __future__ import annotations

from ._auth import resolve_token
from ._client import AplikuClient
from ._exceptions import AuthenticationError
from .resources.apps import AppsResource
from .resources.clusters import ClustersResource
from .resources.cron_jobs import CronJobsResource
from .resources.datastores import DatastoresResource
from .resources.deployments import DeploymentsResource
from .resources.domains import DomainsResource
from .resources.invites import InvitesResource
from .resources.migrations import MigrationsResource
from .resources.servers import ServersResource
from .resources.teams import TeamsResource
from .resources.volumes import VolumesResource


class Appliku:
    """Main SDK client. All resources are accessed as properties.

    Usage:
        client = Appliku(token="tok_...")       # explicit
        client = Appliku()                       # reads APPLIKU_TOKEN env var or config file
    """

    def __init__(self, token: str | None = None) -> None:
        resolved = resolve_token(token)
        if not resolved:
            raise AuthenticationError(
                "No token found. Pass token=, set APPLIKU_TOKEN env var, or run `appliku login`."
            )
        self._client = AplikuClient(token=resolved)

        self._teams: TeamsResource | None = None
        self._apps: AppsResource | None = None
        self._deployments: DeploymentsResource | None = None
        self._datastores: DatastoresResource | None = None
        self._domains: DomainsResource | None = None
        self._volumes: VolumesResource | None = None
        self._cron_jobs: CronJobsResource | None = None
        self._clusters: ClustersResource | None = None
        self._servers: ServersResource | None = None
        self._invites: InvitesResource | None = None
        self._migrations: MigrationsResource | None = None

    @property
    def teams(self) -> TeamsResource:
        if self._teams is None:
            self._teams = TeamsResource(self._client)
        return self._teams

    @property
    def apps(self) -> AppsResource:
        if self._apps is None:
            self._apps = AppsResource(self._client)
        return self._apps

    @property
    def deployments(self) -> DeploymentsResource:
        if self._deployments is None:
            self._deployments = DeploymentsResource(self._client)
        return self._deployments

    @property
    def datastores(self) -> DatastoresResource:
        if self._datastores is None:
            self._datastores = DatastoresResource(self._client)
        return self._datastores

    @property
    def domains(self) -> DomainsResource:
        if self._domains is None:
            self._domains = DomainsResource(self._client)
        return self._domains

    @property
    def volumes(self) -> VolumesResource:
        if self._volumes is None:
            self._volumes = VolumesResource(self._client)
        return self._volumes

    @property
    def cron_jobs(self) -> CronJobsResource:
        if self._cron_jobs is None:
            self._cron_jobs = CronJobsResource(self._client)
        return self._cron_jobs

    @property
    def clusters(self) -> ClustersResource:
        if self._clusters is None:
            self._clusters = ClustersResource(self._client)
        return self._clusters

    @property
    def servers(self) -> ServersResource:
        if self._servers is None:
            self._servers = ServersResource(self._client)
        return self._servers

    @property
    def invites(self) -> InvitesResource:
        if self._invites is None:
            self._invites = InvitesResource(self._client)
        return self._invites

    @property
    def migrations(self) -> MigrationsResource:
        if self._migrations is None:
            self._migrations = MigrationsResource(self._client)
        return self._migrations

    def close(self) -> None:
        self._client.close()

    def __enter__(self) -> Appliku:
        return self

    def __exit__(self, *args: object) -> None:
        self.close()
