"""
Result classes for ETL operations.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Any


@dataclass
class LoadResult:
    """
    Result from a load operation.

    rows_loaded is the total affected count (inserted + updated when both are provided).
    inserted and updated are optional; loaders that support upsert (e.g. Postgres) set them.
    When omitted, consumers can treat rows_loaded as total and inserted, and 0 as updated.
    """

    success: bool = True
    rows_loaded: int = 0
    rows_failed: int = 0
    error: str | None = None
    duration_seconds: float | None = None
    inserted: int | None = None
    updated: int | None = None


@dataclass
class BatchResult:
    """Result from processing a single batch."""

    batch_index: int
    rows_in: int = 0
    rows_out: int = 0
    rows_failed: int = 0
    errors: list[str] = field(default_factory=list)

    @property
    def success(self) -> bool:
        return len(self.errors) == 0 and self.rows_failed == 0


@dataclass
class PipelineResult:
    """Complete result from running an ETL pipeline."""

    success: bool = True
    rows_extracted: int = 0
    rows_transformed: int = 0
    rows_loaded: int = 0
    rows_failed: int = 0
    # Validation tracking
    rows_quarantined_extract: int = 0  # Records quarantined at extract stage
    rows_quarantined_load: int = 0  # Records quarantined at load stage
    validation_errors_extract: list[str] = field(default_factory=list)
    validation_errors_load: list[str] = field(default_factory=list)
    # Timing
    start_time: datetime | None = None
    end_time: datetime | None = None
    duration_seconds: float | None = None
    batches_processed: int = 0
    batch_results: list[BatchResult] = field(default_factory=list)
    errors: list[str] = field(default_factory=list)
    pipeline_name: str | None = None
    run_id: str | None = None
    quality_report: Any = None  # QualityReport | None (Any avoids circular import)
    lineage_events: list[dict[str, Any]] = field(default_factory=list)

    @property
    def total_quarantined(self) -> int:
        """Total records quarantined at both extract and load stages."""
        return self.rows_quarantined_extract + self.rows_quarantined_load

    def to_dict(self) -> dict[str, Any]:
        return {
            "success": self.success,
            "rows_extracted": self.rows_extracted,
            "rows_transformed": self.rows_transformed,
            "rows_loaded": self.rows_loaded,
            "rows_failed": self.rows_failed,
            "rows_quarantined_extract": self.rows_quarantined_extract,
            "rows_quarantined_load": self.rows_quarantined_load,
            "total_quarantined": self.total_quarantined,
            "validation_errors_extract": self.validation_errors_extract,
            "validation_errors_load": self.validation_errors_load,
            "duration_seconds": self.duration_seconds,
            "batches_processed": self.batches_processed,
            "errors": self.errors,
            "pipeline_name": self.pipeline_name,
            "run_id": self.run_id,
            "lineage_events": self.lineage_events,
            "quality_report": (
                self.quality_report.to_dict()
                if self.quality_report is not None
                else None
            ),
        }
