"""
Protocol definitions for ETL components.

Uses Python's Protocol for structural subtyping (duck typing with type hints).
"""

from __future__ import annotations

from typing import Any, AsyncIterator, Protocol, runtime_checkable

from pycharter.etl_generator.result import LoadResult


@runtime_checkable
class Extractor(Protocol):
    """
    Protocol for data extractors.

    Extractors read data from sources (HTTP, files, databases, cloud storage)
    and yield batches of records.
    """

    async def extract(self, **params) -> AsyncIterator[list[dict[str, Any]]]:
        """
        Extract data from the source.

        Yields:
            Batches of records (list of dicts)
        """
        ...


@runtime_checkable
class AckableExtractor(Extractor, Protocol):
    """Extractor that supports batch acknowledgment for at-least-once delivery.

    Message queue extractors (Kafka, RabbitMQ, SQS) implement this to
    enable acknowledgment after successful batch processing.
    """

    async def acknowledge(self, batch_index: int, success: bool) -> None:
        """Acknowledge a batch after processing.

        Args:
            batch_index: The batch number (0-indexed) to acknowledge.
            success: True if batch was loaded successfully, False to signal retry.
        """
        ...


@runtime_checkable
class Transformer(Protocol):
    """
    Protocol for data transformers.

    Transformers process batches of records. They can be chained with |.
    """

    def transform(self, data: list[dict[str, Any]]) -> list[dict[str, Any]]:
        """Transform a batch of records."""
        ...


@runtime_checkable
class Loader(Protocol):
    """
    Protocol for data loaders.

    Loaders write data to destinations (databases, files, cloud storage).
    """

    async def load(self, data: list[dict[str, Any]], **params) -> LoadResult:
        """Load data to the destination."""
        ...
