"""Dataset resource client."""

from __future__ import annotations

from convexity_api_client import AuthenticatedClient, Client
from convexity_api_client.api.v1 import (
    create_dataset_v1_datasets_post as _create_dataset,
)
from convexity_api_client.api.v1 import (
    delete_dataset_v1_datasets_dataset_id_delete as _delete_dataset,
)
from convexity_api_client.api.v1 import (
    get_dataset_v1_datasets_dataset_id_get as _get_dataset,
)
from convexity_api_client.api.v1 import (
    get_refresh_task_status_v1_datasets_dataset_id_refresh_task_id_get as _get_refresh_status,
)
from convexity_api_client.api.v1 import (
    list_datasets_v1_datasets_get as _list_datasets,
)
from convexity_api_client.api.v1 import (
    list_refresh_tasks_v1_datasets_dataset_id_refresh_history_get as _list_refresh_tasks,
)
from convexity_api_client.api.v1 import (
    refresh_dataset_async_v1_datasets_dataset_id_refresh_async_post as _refresh_dataset,
)
from convexity_api_client.api.v1 import (
    update_dataset_v1_datasets_dataset_id_patch as _update_dataset,
)
from convexity_api_client.models.create_dataset_request import CreateDatasetRequest
from convexity_api_client.models.dataset_config import DatasetConfig
from convexity_api_client.models.dataset_definition import DatasetDefinition
from convexity_api_client.models.dataset_list_response import DatasetListResponse
from convexity_api_client.models.dataset_type import DatasetType
from convexity_api_client.models.refresh_mode import RefreshMode
from convexity_api_client.models.refresh_task_list_response import RefreshTaskListResponse
from convexity_api_client.models.update_dataset_request import UpdateDatasetRequest
from convexity_api_client.models.worker_task_response import WorkerTaskResponse
from convexity_api_client.types import UNSET, Unset


class Datasets:
    """Synchronous sub-client for dataset operations."""

    def __init__(self, api_client: AuthenticatedClient | Client) -> None:
        self._client = api_client

    # -- CRUD -----------------------------------------------------------------

    def list(self, project_id: str) -> DatasetListResponse:
        """List datasets for a project."""
        result = _list_datasets.sync(client=self._client, project_id=project_id)
        if result is None or not isinstance(result, DatasetListResponse):
            return DatasetListResponse(datasets=[])
        return result

    def get(self, dataset_id: str) -> DatasetDefinition | None:
        """Get a single dataset by ID."""
        result = _get_dataset.sync(dataset_id, client=self._client)
        if isinstance(result, DatasetDefinition):
            return result
        return None

    def create(
        self,
        *,
        project_id: str,
        name: str,
        type_: DatasetType,
        config: DatasetConfig,
        description: str | None = None,
        connection_id: str | None = None,
        refresh_mode: RefreshMode | None = None,
        refresh_schedule: str | None = None,
        cache_ttl_seconds: int | None = None,
        tags: list[str] | None = None,
    ) -> DatasetDefinition:
        """Create a new dataset in a project.

        Dataset names must be valid table identifiers: letters, numbers,
        underscores, and cannot start with a number.
        """
        body = CreateDatasetRequest(
            project_id=project_id,
            name=name,
            type_=type_,
            config=config,
            description=description if description is not None else UNSET,
            connection_id=connection_id if connection_id is not None else UNSET,
            refresh_mode=refresh_mode if refresh_mode is not None else UNSET,
            refresh_schedule=refresh_schedule if refresh_schedule is not None else UNSET,
            cache_ttl_seconds=cache_ttl_seconds if cache_ttl_seconds is not None else UNSET,
            tags=tags if tags is not None else UNSET,
        )
        result = _create_dataset.sync(client=self._client, body=body, project_id=project_id)
        if not isinstance(result, DatasetDefinition):
            raise ValueError(f"Unexpected response when creating dataset: {result}")
        return result

    def update(
        self,
        dataset_id: str,
        *,
        name: str | None = None,
        description: str | None = None,
        connection_id: str | None = None,
        config: DatasetConfig | None = None,
        refresh_mode: RefreshMode | None = None,
        refresh_schedule: str | None = None,
        cache_ttl_seconds: int | None = None,
        tags: list[str] | None = None,
    ) -> DatasetDefinition:
        """Update an existing dataset.

        Dataset names must be valid table identifiers: letters, numbers,
        underscores, and cannot start with a number.
        """
        body = UpdateDatasetRequest(
            name=name if name is not None else UNSET,
            description=description if description is not None else UNSET,
            connection_id=connection_id if connection_id is not None else UNSET,
            config=config if config is not None else UNSET,
            refresh_mode=refresh_mode if refresh_mode is not None else UNSET,
            refresh_schedule=refresh_schedule if refresh_schedule is not None else UNSET,
            cache_ttl_seconds=cache_ttl_seconds if cache_ttl_seconds is not None else UNSET,
            tags=tags if tags is not None else UNSET,
        )
        result = _update_dataset.sync(dataset_id, client=self._client, body=body)
        if not isinstance(result, DatasetDefinition):
            raise ValueError(f"Unexpected response when updating dataset: {result}")
        return result

    def delete(self, dataset_id: str) -> None:
        """Delete a dataset by ID."""
        _delete_dataset.sync_detailed(dataset_id, client=self._client)

    # -- Refresh --------------------------------------------------------------

    def refresh(self, dataset_id: str) -> WorkerTaskResponse:
        """Trigger an async refresh for a dataset.

        Returns a ``WorkerTaskResponse`` whose ``id`` field is the task ID.
        Use :meth:`get_refresh_status` to poll for completion.
        """
        result = _refresh_dataset.sync(dataset_id, client=self._client)
        if not isinstance(result, WorkerTaskResponse):
            raise ValueError(f"Unexpected response when refreshing dataset: {result}")
        return result

    def get_refresh_status(self, dataset_id: str, task_id: str) -> WorkerTaskResponse:
        """Get the status of a refresh task."""
        result = _get_refresh_status.sync(dataset_id, task_id, client=self._client)
        if not isinstance(result, WorkerTaskResponse):
            raise ValueError(f"Unexpected response when fetching refresh status: {result}")
        return result

    def cancel_refresh(self, dataset_id: str, task_id: str) -> WorkerTaskResponse:
        """Cancel a pending refresh task for a dataset."""
        response = self._client.get_httpx_client().request(
            "post",
            f"/v1/datasets/{dataset_id}/refresh/{task_id}/cancel",
        )
        if response.status_code == 200:
            return WorkerTaskResponse.from_dict(response.json())
        raise ValueError(f"Unexpected response when cancelling refresh task: {response.status_code} {response.text}")

    def list_refresh_history(
        self,
        dataset_id: str,
        *,
        limit: int | None = None,
        offset: int | None = None,
    ) -> RefreshTaskListResponse:
        """List refresh task history for a dataset."""
        limit_arg: int | Unset = UNSET if limit is None else limit
        offset_arg: int | Unset = UNSET if offset is None else offset
        result = _list_refresh_tasks.sync(
            dataset_id,
            client=self._client,
            limit=limit_arg,
            offset=offset_arg,
        )
        if not isinstance(result, RefreshTaskListResponse):
            raise ValueError(f"Unexpected response when listing refresh history: {result}")
        return result
