"""
S3 operations for reference data management.

Provides download and upload commands with automatic versioning for local-first
reference data workflow.
"""

from pathlib import Path
from typing import Optional

import typer
from rich.console import Console
from rich.table import Table

from src.services.s3_data_service import S3DataService
from src.services.environment_service import env_service
from src.services.versioning.local_cache_manager import LocalCacheManager
from src.services.versioning.version_manager import VersionManager
from src.services.versioning.sync_manager import SyncManager

console = Console()
app = typer.Typer(help="S3 reference data operations")


@app.command()
def download(
    force: bool = typer.Option(
        False, "--force", "-f", help="Force download even if local changes exist"
    ),
):
    """Download current reference data from S3 to local cache."""
    try:
        # FAIL FAST: Validate AWS credentials before any work
        env_service.validate_aws_credentials_and_access()

        # Initialize services
        s3_service = S3DataService()
        cache_manager = LocalCacheManager()
        version_manager = VersionManager(s3_service)
        sync_manager = SyncManager(cache_manager, version_manager, s3_service)

        console.print("🔍 Checking sync status...")
        sync_status = sync_manager.get_sync_status()

        if sync_status.is_synced and not force:
            console.print("✅ Local cache is already synced with S3", style="green")
            return

        if sync_status.local_ahead and not force:
            console.print("⚠️  Local cache has changes that will be overwritten", style="yellow")
            console.print("   Use --force to proceed or 'czbg data upload' to save changes first")
            raise typer.Exit(1)

        console.print("🔄 Downloading reference data from S3...")

        sync_manager.download_from_s3(force=force)

        console.print("✅ Reference data downloaded successfully!", style="green")

        # Show updated cache info
        cache_info = cache_manager.get_cache_info()
        if cache_info:
            console.print(f"📊 Local cache: {cache_info.record_count:,} combinations")
            console.print(f"💾 Cache size: {cache_info.file_size_mb:.1f} MB")
            console.print(f"📁 Location: {cache_info.file_path}")

    except FileNotFoundError as e:
        console.print(f"❌ {e}", style="red")
        raise typer.Exit(1)
    except ValueError as e:
        console.print(f"❌ {e}", style="red")
        console.print("💡 Use --force to overwrite or 'czbg data upload' to save changes first", style="yellow")
        raise typer.Exit(1)
    except RuntimeError as e:
        console.print(f"❌ {e}", style="red")
        console.print("💡 Check your AWS credentials and S3 configuration", style="yellow")
        raise typer.Exit(1)
    except Exception as e:
        console.print(f"❌ Download failed: {e}", style="red")
        console.print("💡 Check your AWS credentials and network connection", style="yellow")
        raise typer.Exit(1)


@app.command()
def upload(
    force: bool = typer.Option(
        False, "--force", "-f", help="Upload even if no local changes detected"
    ),
):
    """Upload local changes to S3 with automatic version backup."""
    try:
        # FAIL FAST: Validate AWS credentials before any work
        env_service.validate_aws_credentials_and_access()

        # Initialize services
        s3_service = S3DataService()
        cache_manager = LocalCacheManager()
        version_manager = VersionManager(s3_service)
        sync_manager = SyncManager(cache_manager, version_manager, s3_service)

        console.print("🔍 Checking for local changes...")

        # Check sync status
        sync_status = sync_manager.get_sync_status()

        if sync_status.is_synced and not force:
            console.print("✅ Local cache is already synced with S3", style="green")
            console.print("   No changes to upload")
            return

        if not sync_status.local_ahead and not force:
            console.print("ℹ️  No local changes detected", style="yellow")
            console.print("   Use --force to upload anyway or make local changes first")
            return

        console.print("🔄 Uploading local changes to S3...")
        console.print("   • Creating backup of current S3 data")
        console.print("   • Uploading local cache to S3 current")
        console.print("   • Updating sync manifest")

        result = sync_manager.upload_with_versioning(force=force)

        if result.success:
            console.print("✅ Upload completed successfully!", style="green")

            if result.backup_version == "initial":
                console.print("🎉 Initial upload - no backup needed")
            else:
                console.print(f"📦 Backup version: {result.backup_version}")
                console.print("💡 Use 'czbg data rollback' if you need to undo this upload")

            console.print(f"🔄 New current checksum: {result.new_current_checksum[:8]}...")
        else:
            console.print(f"❌ Upload failed: {result.error_message}", style="red")
            raise typer.Exit(1)

    except ValueError as e:
        console.print(f"❌ Validation error: {e}", style="red")
        console.print("💡 Check your local cache data and S3 configuration", style="yellow")
        raise typer.Exit(1)
    except Exception as e:
        console.print(f"❌ Upload failed: {e}", style="red")
        raise typer.Exit(1)


@app.command(name="sync-status")
def sync_status():
    """Show sync status between local cache and S3."""
    try:
        # FAIL FAST: Validate AWS credentials before any work
        env_service.validate_aws_credentials_and_access()

        # Initialize services
        s3_service = S3DataService()
        cache_manager = LocalCacheManager()
        version_manager = VersionManager(s3_service)
        sync_manager = SyncManager(cache_manager, version_manager, s3_service)

        console.print("🔍 Checking sync status...", style="dim")
        sync_status = sync_manager.get_sync_status()

        console.print()
        console.print("📊 Sync Status", style="bold blue")
        console.print()

        # Create status table
        status_table = Table(show_header=False, box=None, padding=(0, 2))
        status_table.add_column("Status", style="cyan")
        status_table.add_column("Value", style="white")

        # Sync status
        if sync_status.is_synced:
            status_icon = "✅ Synced"
            status_style = "green"
        elif sync_status.local_ahead:
            status_icon = "⬆️  Local ahead"
            status_style = "yellow"
        elif sync_status.remote_ahead:
            status_icon = "⬇️  Remote ahead"
            status_style = "blue"
        else:
            status_icon = "❓ Unknown"
            status_style = "dim"

        status_table.add_row("Overall Status", f"[{status_style}]{status_icon}[/{status_style}]")
        status_table.add_row("Recommendation", sync_status.recommendation.title())

        if sync_status.local_checksum:
            status_table.add_row("Local Checksum", sync_status.local_checksum[:8] + "...")
        if sync_status.remote_checksum:
            status_table.add_row("Remote Checksum", sync_status.remote_checksum[:8] + "...")

        console.print(status_table)
        console.print()

        # Show local cache info
        cache_info = cache_manager.get_cache_info()
        if cache_info:
            console.print("💾 Local Cache", style="bold cyan")
            console.print(f"   • Records: {cache_info.record_count:,} combinations")
            console.print(f"   • Size: {cache_info.file_size_mb:.1f} MB")
            console.print(f"   • Modified: {cache_info.modified_time.strftime('%Y-%m-%d %H:%M:%S')}")
            console.print(f"   • Has Changes: {'Yes' if cache_info.has_local_changes else 'No'}")
            console.print()

        # Show next actions
        console.print("💡 Next Actions:", style="bold yellow")
        if sync_status.recommendation == "upload":
            console.print("   → Run 'czbg data upload' to sync changes to S3")
        elif sync_status.recommendation == "download":
            console.print("   → Run 'czbg data download' to get latest S3 data")
        elif sync_status.recommendation == "synced":
            console.print("   → Everything is in sync!")
        else:
            console.print("   → Check your AWS credentials and S3 configuration")

    except Exception as e:
        console.print(f"❌ Status check failed: {e}", style="red")
        raise typer.Exit(1)


@app.command(name="s3-status")
def s3_status():
    """Show S3 configuration and connection status."""
    try:
        # FAIL FAST: Validate AWS credentials before any work
        env_service.validate_aws_credentials_and_access()

        s3_service = S3DataService()

        console.print("🔧 S3 Configuration", style="bold blue")
        console.print()

        # Configuration table
        config_table = Table(show_header=False, box=None, padding=(0, 2))
        config_table.add_column("Setting", style="cyan")
        config_table.add_column("Value", style="white")

        config_table.add_row("Bucket", s3_service.bucket)
        config_table.add_row("Reference Path", s3_service.reference_path)
        config_table.add_row("Region", s3_service.region)
        config_table.add_row("Profile", s3_service.profile or "default")

        console.print(config_table)
        console.print()

        # Test S3 connection
        console.print("🌐 S3 Connection", style="bold blue")
        try:
            _ = s3_service.s3_client
            console.print("   ✅ Connected successfully", style="green")
        except Exception as e:
            console.print(f"   ❌ Connection failed: {e}", style="red")
            console.print("   💡 Check your AWS credentials and .env configuration", style="yellow")

    except Exception as e:
        console.print(f"❌ Status check failed: {e}", style="red")
        raise typer.Exit(1)