"""
Fabric Data Pipeline item.

Provides the Pipeline class for executing and managing Data Pipelines.
"""

from typing import TYPE_CHECKING, Dict, List, Optional, Union, cast, overload

from ..._shared.exceptions import FabiasError
from ..._shared.response import AzResponse
from ._shared import Item, ItemAccessor

if TYPE_CHECKING:
    pass


class PipelineAccessor(ItemAccessor):
    """Accessor for pipeline operations."""

    ITEM_TYPE = "DataPipeline"
    ITEM_CLASS: Optional[type] = None  # Set after Pipeline definition

    @overload
    def __call__(self, identifier: str) -> "Pipeline": ...

    @overload
    def __call__(self, identifier: None = None) -> List["Pipeline"]: ...

    def __call__(self, identifier: Optional[str] = None) -> Union["Pipeline", List["Pipeline"]]:
        """Get pipeline by name/ID or list all pipelines."""
        result = super().__call__(identifier)
        if isinstance(result, list):
            return cast(List["Pipeline"], result)
        return cast("Pipeline", result)

    def add(
        self, name: str, description: Optional[str] = None, folder_id: Optional[str] = None
    ) -> "Pipeline":
        """Create new pipeline."""
        return cast("Pipeline", super().add(name, description, folder_id))


class Pipeline(Item):
    """
    Represents a Microsoft Fabric Data Pipeline.

    Provides methods to execute pipelines and track execution status.

    Examples:
        >>> pipeline = workspace.pipeline("Daily ETL")
        >>> job = pipeline.run()
        >>> job.wait()
        >>> print(f"Status: {job.status}")

        With parameters:

        >>> job = pipeline.run(parameters={
        ...     "StartDate": "2025-01-01",
        ...     "EndDate": "2025-01-31"
        ... })
    """

    ITEM_TYPE = "DataPipeline"
    ITEM_TYPE_DISPLAY = "Pipeline"

    def run(self, parameters: Optional[Dict[str, str]] = None) -> AzResponse:
        """
        Execute the pipeline.

        Starts an asynchronous pipeline run and returns a Job for tracking.

        Args:
            parameters: Optional pipeline parameters as key-value pairs

        Returns:
            Job: Job object for monitoring execution

        Raises:
            FabiasError: If pipeline execution fails to start
        """
        endpoint = (
            f"/workspaces/{self.workspace_id}/items/{self.id}/jobs/instances?jobType=Pipeline"
        )
        body = parameters if parameters else {}

        try:
            return self._client.post(endpoint, data=body)

        except Exception as e:
            raise FabiasError(f"Failed to run pipeline '{self.name}': {e}")

    def __repr__(self) -> str:
        return f"Pipeline(id={self.id}, name={self.name!r})"


# Set class reference after definition
PipelineAccessor.ITEM_CLASS = Pipeline
