from __future__ import annotations

from datetime import date
from typing import Any
from uuid import UUID

from .base import SubclientBase
from ..schemas import (
    DependencyResponse,
    ItemDataResponse,
    ItemRequest,
    QueryRequest,
    QueryResponse,
)


class QueriesClient(SubclientBase):
    async def query_items(self, request: QueryRequest) -> QueryResponse:
        response = await self._client.post(
            self._client.path("/queries/items/search"),
            json=self._client.dump(request),
        )
        return self._client.parse(response, QueryResponse)

    async def query_item_dependencies(
        self,
        request: ItemRequest,
        steps: int = 1,
        limit: int | None = None,
    ) -> list[DependencyResponse]:
        params: dict[str, int] = {"steps": steps}
        if limit is not None:
            params["limit"] = limit

        response = await self._client.post(
            self._client.path("/queries/items/dependencies"),
            json=self._client.dump(request),
            params=params,
        )
        return self._client.parse_list(response, DependencyResponse)

    async def query_item_references(
        self, request: ItemRequest
    ) -> list[ItemDataResponse]:
        response = await self._client.post(
            self._client.path("/queries/items/references"),
            json=self._client.dump(request),
        )
        return self._client.parse_list(response, ItemDataResponse)

    async def query(
        self,
        item_type_id: UUID,
        item_id: UUID | None = None,
        versions: list[str] | None = None,
        valid_at: date | str | None = None,
        include_history: bool = False,
        limit: int | None = None,
        offset: int | None = None,
        filters: list[dict[str, Any]] | None = None,
        order_by: list[dict[str, Any]] | None = None,
    ) -> QueryResponse:
        parsed_valid_at: date | None
        if isinstance(valid_at, str):
            parsed_valid_at = date.fromisoformat(valid_at)
        else:
            parsed_valid_at = valid_at

        request = QueryRequest(
            item_type_id=item_type_id,
            item_id=item_id,
            versions=versions or [],
            valid_at=parsed_valid_at,
            include_history=include_history,
            limit=limit,
            offset=offset,
            filters=filters or [],
            order_by=order_by or [],
        )
        return await self.query_items(request)

    async def get_item_dependencies(
        self, item_type_id: UUID, item_id: UUID, version: str
    ) -> list[DependencyResponse]:
        request = ItemRequest(
            item_type_id=item_type_id,
            aggregate_id=item_id,
            version=version,
        )
        return await self.query_item_dependencies(request)
