"""Facade client.

`ZenhubClient` wires together a GraphQL executor and domain-specific services.

Design pattern: **Facade**.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any, Mapping

from zenhub_client.constants import ZENHUB_GRAPHQL_ENDPOINT
from zenhub_client.graphql import GraphQLClient, RequestsGraphQLClient
from zenhub_client.services.issues import IssueService
from zenhub_client.services.pipelines import PipelineService
from zenhub_client.services.sprints import SprintService


@dataclass(slots=True)
class ZenhubClient:
    """High-level Zenhub client.

    Consumers can use the `issues`, `pipelines`, and `sprints` service properties.

    Example:
        client = ZenhubClient(api_token="...")
        sprint = client.sprints.get_current_open_sprint(workspace_id)
    """

    _graphql: GraphQLClient
    issues: IssueService
    pipelines: PipelineService
    sprints: SprintService

    def __init__(
        self,
        api_token: str,
        *,
        endpoint: str | None = None,
        timeout_s: int = 30,
        graphql: GraphQLClient | None = None,
    ):
        if graphql is None:
            self._graphql = RequestsGraphQLClient(
                api_token=api_token,
                endpoint=endpoint or ZENHUB_GRAPHQL_ENDPOINT,
                timeout_s=timeout_s,
            )
        else:
            self._graphql = graphql

        self.issues = IssueService(self._graphql)
        self.pipelines = PipelineService(self._graphql)
        self.sprints = SprintService(self._graphql)

    def close(self) -> None:
        """Close underlying resources (if any)."""
        close = getattr(self._graphql, "close", None)
        if callable(close):
            close()

    # --------------------
    # Convenience passthrough
    # --------------------
    def graphql(self, query: str, variables: Mapping[str, Any] | None = None) -> dict[str, Any]:
        """Execute a raw GraphQL query/mutation (escape hatch)."""
        return self._graphql.execute(query, variables)
