"""
Fluent PipelineBuilder API.
"""

from __future__ import annotations

from typing import Any

from pycharter.etl_generator.context import PipelineContext
from pycharter.etl_generator.pipeline import Pipeline
from pycharter.etl_generator.protocols import Extractor, Loader, Transformer


class PipelineBuilder:
    """
    Fluent API for building ETL pipelines.

    Example:
        >>> pipeline = (
        ...     PipelineBuilder()
        ...     .name("user_pipeline")
        ...     .extract_from("http", url="https://api.example.com/users")
        ...     .transform(Rename({"old": "new"}))
        ...     .load_to("postgres", table="users", connection_string="...")
        ...     .build()
        ... )
    """

    def __init__(self):
        self._name: str | None = None
        self._extractor: Extractor | None = None
        self._transformers: list[Transformer] = []
        self._loader: Loader | None = None
        self._context: PipelineContext | None = None

    def name(self, name: str) -> "PipelineBuilder":
        """Set pipeline name."""
        self._name = name
        return self

    def with_context(self, context: PipelineContext) -> "PipelineBuilder":
        """Set pipeline context."""
        self._context = context
        return self

    def extract_from(self, source_type: str, **config) -> "PipelineBuilder":
        """Configure extractor by type."""
        self._extractor = self._create_extractor(source_type, config)
        return self

    def extractor(self, extractor: Extractor) -> "PipelineBuilder":
        """Set extractor directly."""
        self._extractor = extractor
        return self

    def transform(self, transformer: Transformer) -> "PipelineBuilder":
        """Add transformer to pipeline."""
        self._transformers.append(transformer)
        return self

    def load_to(self, target_type: str, **config) -> "PipelineBuilder":
        """Configure loader by type."""
        self._loader = self._create_loader(target_type, config)
        return self

    def loader(self, loader: Loader) -> "PipelineBuilder":
        """Set loader directly."""
        self._loader = loader
        return self

    def build(self) -> Pipeline:
        """Build the pipeline."""
        if not self._extractor:
            raise ValueError("Extractor required. Call extract_from() or extractor()")

        return Pipeline(
            extractor=self._extractor,
            transformers=self._transformers,
            loader=self._loader,
            context=self._context or PipelineContext(),
            name=self._name,
        )

    def _create_extractor(self, source_type: str, config: dict[str, Any]) -> Extractor:
        """Create extractor from type and config via ExtractorFactory."""
        from pycharter.etl_generator.extractors.factory import ExtractorFactory

        return ExtractorFactory.create({"type": source_type, **config})

    def _create_loader(self, target_type: str, config: dict[str, Any]) -> Loader:
        """Create loader from type and config via LoaderFactory."""
        from pycharter.etl_generator.loaders.factory import LoaderFactory

        return LoaderFactory.create({"type": target_type, **config})
