"""
Version management commands for reference data.

Provides commands for listing, backing up, and restoring versions
following the workflow patterns from docs/workflows/reference-data-versioning.md.
"""

import typer
from rich.console import Console
from rich.table import Table
from rich.prompt import Confirm
from typing import Optional

from ..common import BaseCommand
from src.services.s3_data_service import S3DataService
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
from src.services.versioning.models import VersionInfo
from src.services.environment_service import env_service

console = Console()
app = typer.Typer(help="Version management (list, backup, restore)")


class VersionsCommand(BaseCommand):
    """Version management operations for reference data."""

    def __init__(self):
        """Initialize with injected dependencies."""
        super().__init__()
        self.s3_service = S3DataService()
        self.cache_manager = LocalCacheManager()
        self.version_manager = VersionManager(self.s3_service)
        self.sync_manager = SyncManager(self.cache_manager, self.version_manager, self.s3_service)

    def list_versions(self, verbose: bool = False):
        """
        List all available versions with metadata.

        Args:
            verbose: Show detailed information for each version
        """
        try:
            # Validate AWS credentials first
            env_service.validate_aws_credentials_and_access()

            console.print("📋 Listing reference data versions...", style="dim")

            versions = self.version_manager.list_versions()
            manifest = self.version_manager.get_manifest()

            # Determine current version from manifest
            current_version_id = manifest.current_version if manifest else None

            # Mark current version in the backup versions list
            for version in versions:
                version.is_current = (version.version_id == current_version_id)

            # If current version exists but isn't in backup list, add it
            if current_version_id and not any(v.version_id == current_version_id for v in versions):
                # Create a synthetic current version entry for display
                current_version_info = VersionInfo(
                    version_id=current_version_id,
                    created_at=manifest.last_sync,
                    file_size_mb=0.0,  # We don't have size info for current
                    operation="current",
                    checksum="",
                    is_current=True
                )
                versions.insert(0, current_version_info)

            if not versions and not current_version_id:
                console.print("❌ No versions found", style="red")
                console.print()
                console.print("💡 Create your first version by adding data:", style="dim")
                console.print("   czbg data add export <file>", style="dim cyan")
                return

            # Create table for version display
            table = Table(
                title="Reference Data Versions",
                show_header=True,
                header_style="bold blue"
            )

            table.add_column("Version ID", style="cyan", no_wrap=True)
            table.add_column("Created", style="green")
            table.add_column("Size (MB)", justify="right", style="yellow")
            table.add_column("Status", style="magenta")

            if verbose:
                table.add_column("Trigger", style="dim white")

            # Sort versions: current first, then by creation time (newest first)
            versions.sort(key=lambda v: (not v.is_current, -v.created_at.timestamp()))

            # Add version rows
            for version in versions:
                status = "✅ CURRENT" if version.is_current else "📦 Archived"

                # Handle size display for current version that might not have size info
                if version.file_size_mb > 0:
                    size_str = f"{version.file_size_mb:.1f}"
                else:
                    size_str = "N/A" if version.is_current else "0.0"

                created_str = version.created_at.strftime("%Y-%m-%d %H:%M:%S UTC")

                row = [version.version_id, created_str, size_str, status]

                if verbose and hasattr(version, 'trigger_reason') and version.trigger_reason:
                    row.append(version.trigger_reason or "Manual")

                table.add_row(*row)

            console.print()
            console.print(table)
            console.print()

            # Show usage hints
            console.print("📖 Commands:", style="dim")
            console.print("  czbg data versions restore --version <id>  # Restore to specific version", style="dim cyan")
            console.print("  czbg data rollback                          # Undo last operation", style="dim cyan")

        except Exception as e:
            console.print(f"❌ Error listing versions: {e}", style="red")

    def show_current_version(self):
        """Show information about the current active version."""
        try:
            # Validate AWS credentials first
            env_service.validate_aws_credentials_and_access()

            manifest = self.version_manager.get_manifest()

            if not manifest:
                console.print("❌ No current version found", style="red")
                console.print("💡 Upload data first to create a version", style="dim")
                return

            console.print("📋 Current Version Information", style="bold blue")
            console.print()

            info_table = Table(show_header=False, box=None, padding=(0, 2))
            info_table.add_column("Property", style="cyan")
            info_table.add_column("Value", style="white")

            info_table.add_row("Version ID", manifest.current_version)
            info_table.add_row("Last Sync", manifest.last_sync.strftime("%Y-%m-%d %H:%M:%S UTC"))
            info_table.add_row("Last Operation", manifest.last_operation.title())
            info_table.add_row("Total Versions", f"{manifest.total_versions}")
            info_table.add_row("Status", "✅ Current")

            console.print(info_table)
            console.print()

        except Exception as e:
            console.print(f"❌ Error getting current version: {e}", style="red")

    def create_manual_backup(self, reason: str = "Manual backup"):
        """Create a manual backup of the current reference data."""
        try:
            # Validate AWS credentials first
            env_service.validate_aws_credentials_and_access()

            console.print(f"📦 Creating backup: {reason}...", style="dim")

            version_id = self.version_manager.create_version_backup(reason)

            console.print(f"✅ Backup created successfully", style="green")
            console.print()

            # Display backup information
            info_table = Table(show_header=False, box=None, padding=(0, 2))
            info_table.add_column("Property", style="cyan")
            info_table.add_column("Value", style="white")

            info_table.add_row("Version ID", version_id)
            info_table.add_row("Reason", reason)

            console.print(info_table)
            console.print()

            console.print("💡 Use 'czbg data versions list' to see all versions", style="dim")

        except Exception as e:
            console.print(f"❌ Error creating backup: {e}", style="red")

    def restore_version(self, version_id: str, force: bool = False):
        """Restore a specific version as the current reference data."""
        try:
            # Validate AWS credentials first
            env_service.validate_aws_credentials_and_access()

            # Validate version exists
            if not self.version_manager.version_exists(version_id):
                console.print(f"❌ Version not found: {version_id}", style="red")
                console.print()
                console.print("💡 Use 'czbg data versions list' to see available versions", style="dim")
                return

            # Get version info for confirmation
            versions = self.version_manager.list_versions()
            target_version = next((v for v in versions if v.version_id == version_id), None)

            if not target_version:
                console.print(f"❌ Could not get version info for: {version_id}", style="red")
                return

            # Show what will happen
            console.print("🔄 Version Restore Operation", style="bold blue")
            console.print()

            info_table = Table(show_header=False, box=None, padding=(0, 2))
            info_table.add_column("Property", style="cyan")
            info_table.add_column("Value", style="white")

            info_table.add_row("Target Version", target_version.version_id)
            info_table.add_row("Created", target_version.created_at.strftime("%Y-%m-%d %H:%M:%S UTC"))
            info_table.add_row("Size", f"{target_version.file_size_mb:.1f} MB")

            console.print(info_table)
            console.print()

            # Confirmation prompt
            if not force:
                console.print("⚠️  This operation will:", style="bold yellow")
                console.print("  • Create a backup of current data before restoring", style="dim")
                console.print(f"  • Replace current reference data with version {version_id}", style="dim")
                console.print("  • Update the current version pointer", style="dim")
                console.print()

                if not Confirm.ask("Do you want to proceed with the restore?", default=False):
                    console.print("❌ Operation cancelled by user", style="yellow")
                    return

            # Perform restore (version manager creates backup automatically)
            console.print(f"🔄 Restoring version {version_id}...", style="dim")
            console.print("   • Creating backup of current state", style="dim")
            console.print("   • Restoring version to S3 current", style="dim")
            console.print("   • Downloading to local cache", style="dim")

            restore_success = self.version_manager.restore_version(version_id)

            if restore_success:
                # Update local cache with restored data
                self.sync_manager.download_from_s3(force=True)

                console.print("✅ Version restored successfully!", style="green")
                console.print()

                result_table = Table(show_header=False, box=None, padding=(0, 2))
                result_table.add_column("Property", style="cyan")
                result_table.add_column("Value", style="white")

                result_table.add_row("Restored Version", version_id)
                result_table.add_row("Status", "✅ Active")

                console.print(result_table)
                console.print()

                console.print("💡 Use 'czbg data status overview' to verify the restored data", style="dim")

            else:
                console.print("❌ Version restore failed", style="red")

        except Exception as e:
            console.print(f"❌ Error restoring version: {e}", style="red")

    def rollback_last_operation(self, force: bool = False):
        """Rollback to the most recent backup (undo last operation)."""
        try:
            # Validate AWS credentials first
            env_service.validate_aws_credentials_and_access()

            # Get version list to find most recent version
            versions = self.version_manager.list_versions()

            if len(versions) < 1:
                console.print("❌ No backup versions available for rollback", style="red")
                console.print("💡 Upload some data first to create versions", style="dim")
                return

            # Most recent version (should be newest backup)
            target_version = versions[0]  # Already sorted newest first

            # Show rollback operation
            console.print("⏪ Rollback Operation", style="bold blue")
            console.print()

            console.print("🔄 This will:")
            console.print(f"   • Create backup of current S3 state")
            console.print(f"   • Restore S3 current to version: {target_version.version_id}")
            console.print(f"   • Download restored data to local cache")
            console.print()

            rollback_table = Table(show_header=False, box=None, padding=(0, 2))
            rollback_table.add_column("Property", style="cyan")
            rollback_table.add_column("Value", style="white")

            rollback_table.add_row("Target Version", target_version.version_id)
            rollback_table.add_row("Created", target_version.created_at.strftime("%Y-%m-%d %H:%M:%S UTC"))
            rollback_table.add_row("Size", f"{target_version.file_size_mb:.1f} MB")

            console.print(rollback_table)
            console.print()

            # Confirmation
            if not force:
                console.print("⚠️  This will restore your data to the previous version", style="bold yellow")
                console.print("   Current state will be backed up automatically", style="dim")
                console.print()

                if not Confirm.ask("Do you want to rollback to the previous version?", default=False):
                    console.print("❌ Rollback cancelled by user", style="yellow")
                    return

            # Perform rollback
            console.print(f"⏪ Rolling back to {target_version.version_id}...", style="dim")

            success = self.version_manager.restore_version(target_version.version_id)

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

                # Update local cache with restored data
                console.print("📥 Updating local cache...", style="dim")
                self.sync_manager.download_from_s3(force=True)

                console.print("💡 Use 'czbg data sync-status' to verify the rollback", style="dim")
            else:
                console.print("❌ Rollback failed", style="red")

        except Exception as e:
            console.print(f"❌ Error during rollback: {e}", style="red")

    def cleanup_old_versions(self, keep_count: int = 10, force: bool = False):
        """Clean up old version backups, keeping only the most recent ones."""
        try:
            # Validate AWS credentials first
            env_service.validate_aws_credentials_and_access()

            console.print("🧹 Analyzing versions for cleanup...", style="dim")

            versions = self.version_manager.list_versions()
            total_versions = len(versions)

            if total_versions <= keep_count:
                console.print(f"ℹ️ Only {total_versions} versions exist (keeping {keep_count}) - no cleanup needed", style="yellow")
                return

            versions_to_delete = total_versions - keep_count
            old_versions = versions[keep_count:]  # Already sorted newest first

            # Show cleanup preview
            console.print("🧹 Version Cleanup Preview", style="bold blue")
            console.print()

            cleanup_table = Table(show_header=False, box=None, padding=(0, 2))
            cleanup_table.add_column("Property", style="cyan")
            cleanup_table.add_column("Value", style="white")

            cleanup_table.add_row("Total Versions", f"{total_versions:,}")
            cleanup_table.add_row("Versions to Keep", f"{keep_count:,}")
            cleanup_table.add_row("Versions to Delete", f"{versions_to_delete:,}")

            console.print(cleanup_table)

            if old_versions:
                console.print("\n📄 Versions to be deleted (oldest first):", style="bold cyan")
                delete_table = Table(show_header=True, header_style="bold blue")
                delete_table.add_column("Version ID", style="cyan")
                delete_table.add_column("Created", style="green")
                delete_table.add_column("Size (MB)", justify="right", style="yellow")

                # Show oldest first for deletion list
                for version in reversed(old_versions):
                    delete_table.add_row(
                        version.version_id,
                        version.created_at.strftime("%Y-%m-%d %H:%M"),
                        f"{version.file_size_mb:.1f}"
                    )

                console.print(delete_table)
                console.print()

            # Confirmation
            if not force:
                total_size_mb = sum(v.file_size_mb for v in old_versions)
                console.print(f"⚠️  This will permanently delete {versions_to_delete} old version(s)", style="bold yellow")
                console.print(f"   Total storage to free: {total_size_mb:.1f} MB", style="dim")
                console.print()

                if not Confirm.ask("Do you want to proceed with cleanup?", default=False):
                    console.print("❌ Cleanup cancelled by user", style="yellow")
                    return

            # Perform cleanup
            console.print("🧹 Cleaning up old versions...", style="dim")
            deleted_count = self.version_manager.cleanup_old_versions(keep_count)

            if deleted_count > 0:
                console.print(f"✅ Successfully deleted {deleted_count} old version(s)", style="green")
                console.print(f"💡 Kept {keep_count} most recent versions", style="dim")
            else:
                console.print("❌ No versions were deleted", style="red")

        except Exception as e:
            console.print(f"❌ Error during cleanup: {e}", style="red")


@app.command("list")
def list_versions(
    verbose: bool = typer.Option(False, "--verbose", "-v", help="Show detailed information")
):
    """List all available versions."""
    # Lazy initialization - create instance only when command executes
    VersionsCommand().list_versions(verbose=verbose)


@app.command("current")
def show_current():
    """Show current version information."""
    # Lazy initialization - create instance only when command executes
    VersionsCommand().show_current_version()


@app.command("backup")
def create_backup(
    reason: str = typer.Option("Manual backup", "--reason", "-r", help="Reason for creating this backup")
):
    """Create a manual backup of current reference data."""
    # Lazy initialization - create instance only when command executes
    VersionsCommand().create_manual_backup(reason=reason)


@app.command("restore")
def restore_version(
    version: str = typer.Option(..., "--version", help="Version ID to restore"),
    force: bool = typer.Option(False, "--force", help="Skip confirmation prompts")
):
    """Restore a specific version as current reference data."""
    # Lazy initialization - create instance only when command executes
    VersionsCommand().restore_version(version_id=version, force=force)


@app.command("cleanup")
def cleanup_versions(
    keep_count: int = typer.Option(10, "--keep", help="Number of recent versions to keep"),
    force: bool = typer.Option(False, "--force", help="Skip confirmation prompts")
):
    """Clean up old version backups, keeping only recent ones."""
    # Lazy initialization - create instance only when command executes
    VersionsCommand().cleanup_old_versions(keep_count=keep_count, force=force)