"""
Export processing orchestrator following Single Responsibility Principle.
"""

from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional, List
import polars as pl

from .export_validator import ExportValidator
from .column_normalizer import ColumnNormalizer
from .combination_extractor import CombinationExtractor
from .pricing_calculator import PricingCalculator
from .quality_validator import QualityValidator, QualityWarning
from src.services.versioning.local_cache_manager import LocalCacheManager


@dataclass
class ProcessingResult:
    """Result of export processing operations."""
    success: bool
    combinations_added: int = 0
    pricing_updates: int = 0
    total_records_processed: int = 0
    unique_combinations_found: int = 0
    records_with_usage: int = 0
    pricing_combinations_calculated: int = 0
    coverage_improvement: float = 0.0
    processing_time_seconds: float = 0.0
    quality_warnings: List[QualityWarning] = field(default_factory=list)
    quality_score: str = "unknown"
    error_message: Optional[str] = None
    # Resource type cleaning and deduplication statistics
    export_resource_types_cleaned: int = 0
    export_duplicates_removed: int = 0
    cache_resource_types_cleaned: int = 0
    cache_duplicates_removed: int = 0


class ExportProcessor:
    """
    Single responsibility: Orchestrate export processing operations.

    Coordinates validation, normalization, combination extraction, and caching
    without implementing the detailed logic of each step.
    """

    def __init__(self,
                 validator: ExportValidator,
                 normalizer: ColumnNormalizer,
                 extractor: CombinationExtractor,
                 pricing_calculator: PricingCalculator,
                 quality_validator: QualityValidator,
                 cache_manager: LocalCacheManager):
        """Initialize with injected dependencies."""
        self.validator = validator
        self.normalizer = normalizer
        self.extractor = extractor
        self.pricing_calculator = pricing_calculator
        self.quality_validator = quality_validator
        self.cache_manager = cache_manager

    def process_export(self, export_path: Path) -> ProcessingResult:
        """
        Process CloudZero export file through complete pipeline.

        Args:
            export_path: Path to export CSV file

        Returns:
            ProcessingResult with operation details
        """
        import time
        start_time = time.time()

        try:
            # Load export file with progress indication
            export_df = self._load_export_csv(export_path)
            if export_df.is_empty():
                return ProcessingResult(
                    success=False,
                    error_message="Export file contains no data"
                )

            # Validate schema
            validation_result = self.validator.validate_export_schema(export_df)
            if not validation_result.is_valid:
                return ProcessingResult(
                    success=False,
                    error_message=validation_result.error_message
                )

            # Track export cleaning statistics before normalization
            export_resource_types_cleaned = self.normalizer.count_resource_types_needing_cleaning(export_df)

            # Normalize columns and clean data (includes resource_type cleaning)
            normalized_df = self.normalizer.normalize_export_columns(export_df)

            # Add has_pricing flag for combination tracking
            processed_df = self._add_pricing_flag(normalized_df)

            # Deduplicate export data and track statistics
            deduplicated_df, export_duplicates_removed = self.cache_manager.deduplicate_combinations(processed_df)

            # Execute dual operations on deduplicated data
            # Operation 1: Extract unique combinations
            combinations = self.extractor.extract_combinations(deduplicated_df)

            # Operation 2: Calculate pricing rates
            pricing = self.pricing_calculator.calculate_pricing_rates(deduplicated_df)

            # Quality validation
            quality_warnings = self._perform_quality_validation(
                export_df, combinations, pricing
            )
            quality_summary = self.quality_validator.generate_quality_summary(quality_warnings)

            # Calculate coverage improvement
            cache_info_before = self.cache_manager.get_cache_info()
            initial_count = cache_info_before.record_count if cache_info_before else 0

            # Merge both operations into cache
            merge_result = self.cache_manager.merge_dual_operations(
                combinations, pricing
            )
            combinations_added = merge_result["new_combinations"]
            pricing_updates = merge_result["pricing_updates"]

            # Extract cache cleaning statistics
            cache_resource_types_cleaned = merge_result.get("cache_resource_types_cleaned", 0)
            cache_duplicates_removed = merge_result.get("cache_duplicates_removed", 0)

            # Calculate final statistics
            cache_info_after = self.cache_manager.get_cache_info()
            final_count = cache_info_after.record_count if cache_info_after else initial_count
            coverage_improvement = ((final_count - initial_count) / max(initial_count, 1)) * 100

            processing_time = time.time() - start_time
            records_with_usage = self.validator.validate_pricing_data(normalized_df)
            unique_combinations = self.extractor.count_unique_combinations(processed_df)
            pricing_combinations = pricing.height

            return ProcessingResult(
                success=True,
                combinations_added=combinations_added,
                pricing_updates=pricing_updates,
                total_records_processed=export_df.height,
                unique_combinations_found=unique_combinations,
                records_with_usage=records_with_usage,
                pricing_combinations_calculated=pricing_combinations,
                coverage_improvement=coverage_improvement,
                processing_time_seconds=processing_time,
                quality_warnings=quality_warnings,
                quality_score=quality_summary["overall_quality"],
                # Cleaning and deduplication statistics
                export_resource_types_cleaned=export_resource_types_cleaned,
                export_duplicates_removed=export_duplicates_removed,
                cache_resource_types_cleaned=cache_resource_types_cleaned,
                cache_duplicates_removed=cache_duplicates_removed
            )

        except Exception as e:
            processing_time = time.time() - start_time

            # Enhanced error messages with suggestions
            error_message = self._enhance_error_message(str(e), export_path)

            return ProcessingResult(
                success=False,
                processing_time_seconds=processing_time,
                error_message=error_message
            )

    def _load_export_csv(self, export_path: Path) -> pl.DataFrame:
        """Load CSV file with error handling and performance optimization."""
        try:
            # Check file size for performance optimization
            file_size_mb = export_path.stat().st_size / (1024 * 1024)

            if file_size_mb > 100:  # Large file optimization
                # Use lazy loading for large files
                return pl.scan_csv(export_path).collect()
            else:
                # Standard loading for smaller files
                return pl.read_csv(export_path)

        except Exception as e:
            raise ValueError(f"Failed to load CSV file: {e}")

    def _add_pricing_flag(self, df: pl.DataFrame) -> pl.DataFrame:
        """Add has_pricing indicator for combination tracking (actually 'has usage')."""
        if "has_pricing" in df.columns:
            return df

        # Check if we have the required columns for usage data
        required_cols = ["pricing_unit", "real_cost", "usage_amount"]
        has_required_cols = all(col in df.columns for col in required_cols)

        if has_required_cols:
            # Use same logic as PricingCalculator: requires positive cost and usage
            return df.with_columns([
                (pl.col("pricing_unit").is_not_null() &
                 (pl.col("pricing_unit") != "") &
                 (pl.col("real_cost") > 0) &
                 (pl.col("usage_amount") > 0)).alias("has_pricing")
            ])
        else:
            return df.with_columns([
                pl.lit(False).alias("has_pricing")
            ])

    def _perform_quality_validation(self,
                                  export_df: pl.DataFrame,
                                  combinations: pl.DataFrame,
                                  pricing: pl.DataFrame) -> List[QualityWarning]:
        """Perform comprehensive quality validation."""
        all_warnings = []

        # Validate export completeness
        all_warnings.extend(
            self.quality_validator.validate_export_completeness(export_df)
        )

        # Validate combination uniqueness
        all_warnings.extend(
            self.quality_validator.validate_combination_uniqueness(combinations)
        )

        # Validate pricing calculations if available
        if not pricing.is_empty():
            all_warnings.extend(
                self.quality_validator.validate_pricing_calculations(pricing)
            )

        return all_warnings

    def _enhance_error_message(self, error: str, export_path: Path) -> str:
        """Enhance error messages with helpful suggestions."""
        if "Failed to load CSV file" in error:
            return f"{error}\n\nSuggestions:\n- Verify file exists and is readable: {export_path}\n- Check file format is valid CSV\n- Ensure file is not corrupted or empty"

        if "Missing required columns" in error:
            return f"{error}\n\nSuggestions:\n- Verify export contains required columns: Cloud Provider, Service, etc.\n- Check column headers match expected format\n- Ensure export is from CloudZero Analytics (not other tools)"

        if "Schema validation failed" in error:
            return f"{error}\n\nSuggestions:\n- Verify export file format\n- Check for corrupted or truncated data\n- Try re-downloading export from CloudZero"

        return error