from typing import Literal, TypeAlias

from pydantic import Field

from ._base import AnaplanModel


class TaskResultDetail(AnaplanModel):
    local_message_text: str | None = Field(None, description="Error message text.")
    occurrences: int = Field(0, description="The number of occurrences of this error.")
    type: str = Field(description="The type of this error.")
    values: list[str | None] = Field([], description="Further error information if available.")


class TaskResult(AnaplanModel):
    details: list[TaskResultDetail] = Field(
        [], description="The details of this task result if available."
    )
    successful: bool = Field(description="Whether this task completed successfully or not.")
    failure_dump_available: bool = Field(
        description="Whether a failure dump is available for this task."
    )
    nested_results: list["TaskResult"] = Field(
        [], description="The nested results of this task, if available."
    )


class TaskSummary(AnaplanModel):
    id: str = Field(validation_alias="taskId", description="The unique identifier of this task.")
    task_state: Literal["NOT_STARTED", "IN_PROGRESS", "COMPLETE"] = Field(
        description="The state of this task."
    )
    creation_time: int = Field(description="Unix timestamp of when this task was created.")


class Task(TaskSummary):
    task_state: Literal["NOT_STARTED", "IN_PROGRESS"] = Field(description="The state of this task.")  # pyright: ignore[reportIncompatibleVariableOverride]
    progress: float = Field(description="The progress of this task as a float between 0 and 1.")
    current_step: str | None = Field(None, description="The current step of this task.")


class CompletedTask(Task):
    task_state: Literal["COMPLETE"] = Field(description="The state of this task.")  # pyright: ignore[reportIncompatibleVariableOverride]
    result: TaskResult


TaskStatus: TypeAlias = Task | CompletedTask


class _TaskStatusPoll(AnaplanModel):
    task: TaskStatus = Field(discriminator="task_state")


class SyncTaskResult(AnaplanModel):
    source_revision_id: str = Field(description="The ID of the source revision.")
    target_revision_id: str = Field(description="The ID of the target revision.")
    successful: bool = Field(description="Whether the sync task was successful or not.")
    # TODO: Verify if we have results / error details here as well. If so,
    #  add another discriminated union to distinguish between success and failure.


class PendingTask(TaskSummary):
    task_state: Literal["NOT_STARTED", "IN_PROGRESS"] = Field(description="The state of this task.")  # pyright: ignore[reportIncompatibleVariableOverride]
    current_step: str = Field(description="The current step of the sync task.")


class CompletedSyncTask(PendingTask):
    task_state: Literal["COMPLETE"] = Field(description="The state of this task.")  # pyright: ignore[reportIncompatibleVariableOverride]
    result: SyncTaskResult


SyncTask: TypeAlias = PendingTask | CompletedSyncTask


class _SyncTaskStatusPoll(AnaplanModel):
    task: SyncTask = Field(discriminator="task_state")


class ReportTaskResult(SyncTaskResult):
    successful: Literal[True] = Field(description="Whether the sync task was successful or not.")  # pyright: ignore[reportIncompatibleVariableOverride]
    report_file_url: str = Field(
        description="The URL of the report file generated by the sync task."
    )


class ReportTaskError(AnaplanModel):
    title: str = Field(description="The title of the error.")
    message: str = Field(validation_alias="messageText", description="The message of the error.")


class ReportTaskFailureResult(SyncTaskResult):
    successful: Literal[False] = Field(description="Whether the sync task was successful or not.")  # pyright: ignore[reportIncompatibleVariableOverride]
    error: ReportTaskError = Field(description="The error that occurred during the sync task.")


class CompletedReportTask(CompletedSyncTask):
    result: ReportTaskResult | ReportTaskFailureResult = Field(discriminator="successful")  # pyright: ignore[reportIncompatibleVariableOverride]


ReportTask: TypeAlias = PendingTask | CompletedReportTask


class _ReportTaskStatusPoll(AnaplanModel):
    task: ReportTask = Field(discriminator="task_state")
