from __future__ import annotations

from typing import Any
from uuid import UUID

from .base import SubclientBase
from ..schemas import (
    CreateTaskRequest,
    ItemProjectionEventSchema,
    TaskCommandImpactingPayloadResponse,
    TaskResponse,
    TaskSummaryRequest,
    TaskSummaryResponse,
)


class TasksClient(SubclientBase):
    async def create_task(self, request: CreateTaskRequest) -> TaskResponse:
        response = await self._client.post(
            self._client.path("/tasks"), json=self._client.dump(request)
        )
        return self._client.parse(response, TaskResponse)

    async def list_tasks(
        self,
        created_by: UUID | None = None,
        assignee: UUID | None = None,
        offset: int = 0,
        limit: int = 1000,
        item_id: UUID | None = None,
    ) -> list[TaskResponse]:
        params: dict[str, Any] = {
            "offset": offset,
            "limit": limit,
        }
        if created_by is not None:
            params["created_by"] = str(created_by)
        if assignee is not None:
            params["assignee"] = str(assignee)
        if item_id is not None:
            params["itemId"] = str(item_id)

        response = await self._client.get(self._client.path("/tasks"), params=params)
        return self._client.parse_list(response, TaskResponse)

    async def get_task(self, task_id: UUID) -> TaskResponse:
        response = await self._client.get(self._client.path(f"/tasks/{task_id}"))
        return self._client.parse(response, TaskResponse)

    async def summarize_tasks(self, task_ids: list[UUID]) -> list[TaskSummaryResponse]:
        response = await self._client.post(
            self._client.path("/tasks/summary"),
            json=self._client.dump(TaskSummaryRequest(task_ids=task_ids)),
        )
        return self._client.parse_list(response, TaskSummaryResponse)

    async def get_dryrun_created_items(
        self, task_id: UUID, command_uid: UUID
    ) -> list[ItemProjectionEventSchema]:
        response = await self._client.get(
            self._client.path(
                f"/tasks/{task_id}/dry-run/commands/{command_uid}/created"
            )
        )
        return self._client.parse_list(response, ItemProjectionEventSchema)

    async def get_dryrun_retired_items(
        self, task_id: UUID, command_uid: UUID
    ) -> list[ItemProjectionEventSchema]:
        response = await self._client.get(
            self._client.path(
                f"/tasks/{task_id}/dry-run/commands/{command_uid}/retired"
            )
        )
        return self._client.parse_list(response, ItemProjectionEventSchema)

    async def get_dryrun_updated_items(
        self, task_id: UUID, command_uid: UUID
    ) -> list[ItemProjectionEventSchema]:
        response = await self._client.get(
            self._client.path(
                f"/tasks/{task_id}/dry-run/commands/{command_uid}/updated"
            )
        )
        return self._client.parse_list(response, ItemProjectionEventSchema)

    async def get_impacting_commands(
        self, task_id: UUID, command_uid: UUID
    ) -> list[TaskCommandImpactingPayloadResponse]:
        response = await self._client.get(
            self._client.path(
                f"/tasks/{task_id}/dry-run/commands/{command_uid}/impacting-commands"
            )
        )
        return self._client.parse_list(response, TaskCommandImpactingPayloadResponse)

    async def get_referencing_commands(
        self, task_id: UUID, command_uid: UUID
    ) -> list[TaskCommandImpactingPayloadResponse]:
        response = await self._client.get(
            self._client.path(
                f"/tasks/{task_id}/dry-run/commands/{command_uid}/referencing-commands"
            )
        )
        return self._client.parse_list(response, TaskCommandImpactingPayloadResponse)
