"""
Add CloudZero export files to the local reference dataset cache.

All operations work on local cache only. Use 'czbg data upload' to sync changes to S3.
"""

import typer
from pathlib import Path
import polars as pl
from rich.console import Console
from rich.progress import Progress, SpinnerColumn, TextColumn

from ..common import BaseCommand
from src.services.versioning.local_cache_manager import LocalCacheManager
from .services import (
    ExportValidator, ColumnNormalizer, CombinationExtractor,
    PricingCalculator, QualityValidator, ExportProcessor, ProcessingResult
)

console = Console()
app = typer.Typer(help="Add export files to local reference dataset")


class DataAddCommand(BaseCommand):
    """Add export files to local reference dataset cache."""

    def __init__(self):
        """Initialize with dependencies for export processing."""
        super().__init__()

        # Dependency injection following CLAUDE.md principles
        cache_manager = LocalCacheManager()
        validator = ExportValidator()
        normalizer = ColumnNormalizer()
        extractor = CombinationExtractor()
        pricing_calculator = PricingCalculator()
        quality_validator = QualityValidator()

        # Inject dependencies into processor
        self.export_processor = ExportProcessor(
            validator=validator,
            normalizer=normalizer,
            extractor=extractor,
            pricing_calculator=pricing_calculator,
            quality_validator=quality_validator,
            cache_manager=cache_manager
        )

    def add_export_file(self, export_file: str, verbose: bool = False):
        """Add CloudZero export file to the local cache."""
        try:
            export_path = Path(export_file)
            self.validate_file_exists(export_path, "export file")

            # Enhanced file validation
            self._validate_export_file(export_path)

            if verbose:
                console.print(f"[blue]Adding export: {export_path}[/blue]")
                console.print(f"[blue]To local cache: {self.export_processor.cache_manager.cache_path}[/blue]")

            # Process export using orchestrated pipeline with progress
            with Progress(
                SpinnerColumn(),
                TextColumn("{task.description}"),
                console=console,
                transient=True
            ) as progress:
                task_id = progress.add_task("📥 Processing export file...", total=None)
                result = self.export_processor.process_export(export_path)
                progress.update(task_id, completed=True)

            # Handle processing result
            if not result.success:
                raise RuntimeError(result.error_message)

            # Display results
            self._display_processing_result(result, verbose)

            # Display quality summary for non-verbose mode
            if not verbose and result.quality_warnings:
                high_warnings = [w for w in result.quality_warnings if w.severity == "high"]
                if high_warnings:
                    console.print(f"\n⚠️  {len(high_warnings)} high-severity quality issues found. Use --verbose for details.",
                                style="yellow")

            # Show next steps suggestion
            total_changes = result.combinations_added + result.pricing_updates
            if total_changes > 0:
                console.print("\n💡 Next steps:", style="bold blue")
                console.print("   • Run 'czbg data upload --refresh-backup' to share with team")
                console.print("   • Use 'czbg data explore' to analyze updated reference data")
                if result.pricing_updates > 0:
                    console.print("   • Updated pricing will improve usage allocation accuracy")
            elif verbose:
                # Show exploration commands even when no changes
                console.print("\n💡 Explore your data:", style="bold blue")
                console.print("   • czbg data status overview")
                console.print("   • czbg data explore providers")
                console.print("   • Current pricing rates are up-to-date")

        except Exception as e:
            # Enhanced error handling with recovery suggestions
            error_msg = str(e)
            if "Failed to add records to local cache" in error_msg:
                console.print(f"\n⚠️  Cache Error: {error_msg}", style="red")
                console.print("\n💡 Recovery options:", style="yellow")
                console.print("   • Try: czbg data download --force  (refresh local cache)")
                console.print("   • Check disk space and file permissions")
            elif "Missing required columns" in error_msg:
                console.print(f"\n⚠️  Schema Error: {error_msg}", style="red")
                console.print("\n💡 Export requirements:", style="yellow")
                console.print("   • Ensure export includes: Cloud Provider, Service, Usage Family, etc.")
                console.print("   • Use CloudZero Analytics (not other export tools)")
            else:
                self.handle_exception(e, "adding export file")

    def _validate_export_file(self, export_path: Path):
        """Perform enhanced export file validation."""
        # Check file extension
        if export_path.suffix.lower() != '.csv':
            console.print(f"\n⚠️  Expected CSV file, got: {export_path.suffix}", style="yellow")
            console.print("   CloudZero exports should be CSV format")

        # Check file size
        file_size_mb = export_path.stat().st_size / (1024 * 1024)
        if file_size_mb > 500:
            console.print(f"\n⚠️  Large file detected: {file_size_mb:.1f}MB", style="yellow")
            console.print("   Processing may take longer for large exports")
        elif file_size_mb < 0.01:
            console.print(f"\n⚠️  Very small file: {file_size_mb * 1024:.1f}KB", style="yellow")
            console.print("   Verify export contains data")

        # Quick header check
        try:
            with open(export_path, 'r', encoding='utf-8') as f:
                first_line = f.readline().strip()
                if 'Cloud Provider' not in first_line:
                    console.print("\n⚠️  Header check: 'Cloud Provider' column not found", style="yellow")
                    console.print("   Verify this is a CloudZero Analytics export")
        except Exception:
            pass  # Skip header check if file can't be read

    def _display_processing_result(self, result: ProcessingResult, verbose: bool):
        """Display processing result with appropriate detail level."""
        total_changes = result.combinations_added + result.pricing_updates

        # Show export analysis first
        console.print(f"📥 Export contained {result.unique_combinations_found:,} unique combinations")

        # Show cleaning and deduplication statistics
        self._display_cleaning_statistics(result)

        if total_changes > 0:
            # Show summary of changes
            if result.combinations_added > 0 and result.pricing_updates > 0:
                console.print(f"✅ Added {result.combinations_added:,} new combinations and updated {result.pricing_updates:,} pricing records", style="green")
            elif result.combinations_added > 0:
                console.print(f"✅ Added {result.combinations_added:,} new combinations to local cache", style="green")
            elif result.pricing_updates > 0:
                console.print(f"✅ Updated pricing for {result.pricing_updates:,} existing combinations", style="green")

            console.print()

            # Show cache info
            cache_info = self.export_processor.cache_manager.get_cache_info()
            if cache_info:
                console.print(f"📊 Local cache: {cache_info.record_count:,} total combinations", style="dim")
                console.print(f"💾 Cache size: {cache_info.file_size_mb:.1f} MB", style="dim")

            console.print()
            console.print("⚠️  Local changes made - run 'czbg data upload' to sync to S3", style="yellow")
        else:
            existing_combinations = result.unique_combinations_found - result.combinations_added
            console.print(f"ℹ️ No new combinations - all {existing_combinations:,} combinations already exist with current pricing", style="yellow")

        # Show detailed summary if verbose
        if verbose:
            self._display_verbose_summary(result)

    def _display_cleaning_statistics(self, result: ProcessingResult):
        """Display resource type cleaning and deduplication statistics."""
        # Always show export statistics for confidence
        console.print(f"🧹 Export: Cleaned {result.export_resource_types_cleaned:,} resource type prefixes")
        console.print(f"🔄 Export: Removed {result.export_duplicates_removed:,} duplicate combinations")

        # Always show cache statistics for confidence
        console.print(f"🧹 Cache: Cleaned {result.cache_resource_types_cleaned:,} resource type prefixes")
        console.print(f"🔄 Cache: Removed {result.cache_duplicates_removed:,} duplicate combinations")

    def _display_verbose_summary(self, result: ProcessingResult):
        """Display detailed processing summary with quality metrics."""
        try:
            console.print("📋 Export Processing Summary:", style="bold blue")
            console.print(f"   • Total records: {result.total_records_processed:,}")
            console.print(f"   • Unique combinations: {result.unique_combinations_found:,}")
            console.print(f"   • Records with usage: {result.records_with_usage:,}")
            console.print(f"   • New combinations added: {result.combinations_added:,}")
            console.print(f"   • Pricing updates applied: {result.pricing_updates:,}")
            console.print(f"   • Pricing rates calculated: {result.pricing_combinations_calculated:,}")

            # Always show cleaning and deduplication statistics in verbose mode
            console.print(f"   • Export resource types cleaned: {result.export_resource_types_cleaned:,}")
            console.print(f"   • Export duplicates removed: {result.export_duplicates_removed:,}")
            console.print(f"   • Cache resource types cleaned: {result.cache_resource_types_cleaned:,}")
            console.print(f"   • Cache duplicates removed: {result.cache_duplicates_removed:,}")

            if result.coverage_improvement > 0:
                console.print(f"   • Coverage improvement: +{result.coverage_improvement:.1f}%")

            console.print(f"   • Processing time: {result.processing_time_seconds:.2f} seconds")
            console.print(f"   • Data quality: {result.quality_score.title()}",
                         style=self._get_quality_style(result.quality_score))
            console.print()

            # Enhanced operation status
            console.print("   ✅ Operation 1: Reference combinations tracked", style="green")
            if result.pricing_combinations_calculated > 0:
                if result.pricing_updates > 0:
                    console.print(f"   ✅ Operation 2: Pricing updated for {result.pricing_updates:,} combinations", style="green")
                else:
                    console.print("   ✅ Operation 2: Pricing rates calculated for new combinations", style="green")
            else:
                console.print("   ⚠️  Operation 2: No pricing data found", style="yellow")

            # Highlight pricing behavior
            if result.pricing_combinations_calculated > 0:
                console.print()
                console.print("   💡 Pricing updates: All combinations with pricing data are updated to latest rates",
                             style="dim blue")

            # Display quality warnings if any
            self._display_quality_warnings(result.quality_warnings)

        except Exception as e:
            console.print(f"   ⚠️  Could not generate verbose summary: {e}", style="dim yellow")

    def _get_quality_style(self, quality_score: str) -> str:
        """Get console style for quality score."""
        quality_styles = {
            "excellent": "green",
            "good": "green",
            "fair": "yellow",
            "poor": "red",
            "unknown": "dim"
        }
        return quality_styles.get(quality_score, "dim")

    def _display_quality_warnings(self, warnings):
        """Display quality warnings if any exist."""
        if not warnings:
            return

        console.print(f"\n   ⚠️  Quality Warnings ({len(warnings)}):")
        for warning in warnings[:3]:  # Show up to 3 warnings
            style = "red" if warning.severity == "high" else "yellow" if warning.severity == "medium" else "dim"
            console.print(f"     • {warning.message}", style=style)

        if len(warnings) > 3:
            console.print(f"     ... and {len(warnings) - 3} more warnings")


# Create command instance
add_cmd = DataAddCommand()


@app.command()
def export(
    export_file: str = typer.Argument(..., help="Path to CloudZero export CSV file"),
    verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose output")
):
    """Add CloudZero export file to the local reference dataset cache."""
    add_cmd.add_export_file(export_file, verbose)