"""
Custom exceptions for the operator client.
"""


class OperatorError(Exception):
    """Base class for all operator-client errors."""


class TaskExecutionError(OperatorError):
    """Raised when the operator reports task execution failure."""

    def __init__(self, task_id: str, error_message: str, error_details: dict = None):
        self.task_id = task_id
        self.error_message = error_message
        self.error_details = error_details or {}
        super().__init__(f"Task {task_id} failed: {error_message}")


class TaskTimeoutError(OperatorError):
    """Raised when waiting for a task result exceeds the timeout."""

    def __init__(self, task_id: str, timeout: int):
        self.task_id = task_id
        self.timeout = timeout
        super().__init__(f"Task {task_id} timed out after {timeout} seconds")


class InvalidTaskStatusError(OperatorError):
    """Raised when the operator returns an unknown task status."""

    def __init__(self, task_id: str, status: str):
        self.task_id = task_id
        self.status = status
        super().__init__(f"Task {task_id} has unknown status: {status}")


class InvalidResultFormatError(OperatorError):
    """Raised when the operator returns a non-dict payload."""

    def __init__(self, task_id: str, result):
        self.task_id = task_id
        self.result = result
        super().__init__(f"Task {task_id} returned invalid result format: {type(result)}")


class OperatorConnectionError(OperatorError):
    """Raised when the client cannot reach the target operator."""

    def __init__(self, operator_name: str, operator_version: str, reason: str = None):
        self.operator_name = operator_name
        self.operator_version = operator_version
        self.reason = reason
        message = f"Failed to connect to operator {operator_name} v{operator_version}"
        if reason:
            message += f": {reason}"
        super().__init__(message)


class InvalidPriorityError(OperatorError):
    """Raised when a caller provides an unsupported queue priority."""

    def __init__(self, priority: str, valid_priorities: list):
        self.priority = priority
        self.valid_priorities = valid_priorities
        super().__init__(f"Invalid priority: {priority}. Must be one of {valid_priorities}")


class BatchProcessingError(OperatorError):
    """Raised when a batch operation fails across one or more tasks."""

    def __init__(self, failed_tasks: list, total_tasks: int):
        self.failed_tasks = failed_tasks
        self.total_tasks = total_tasks
        super().__init__(f"Batch processing failed: {len(failed_tasks)}/{total_tasks} tasks failed")


class TaskDeadlineExceededError(OperatorError):
    """Raised when the operator skips a task because its deadline expired."""

    def __init__(self, task_id: str, deadline: float, current_time: float):
        self.task_id = task_id
        self.deadline = deadline
        self.current_time = current_time
        super().__init__(f"Task {task_id} exceeded deadline: {deadline} (current: {current_time})")


class TaskCancelledError(OperatorError):
    """Raised when the operator skips a task because its cancel key was set."""

    def __init__(self, task_id: str, cancel_key: str):
        self.task_id = task_id
        self.cancel_key = cancel_key
        super().__init__(f"Task {task_id} was cancelled via cancel_key: {cancel_key}")


class StopException(OperatorError):
    """Internal stop exception used by higher-level control flow."""

    def __init__(self, message: str):
        self.message = message
        super().__init__(message)
