"""CLI commands for metadata stage."""

import logging
from pathlib import Path
from typing import Optional

import typer
from rich.console import Console

from ..config.models import MetadataConfig
from ..config.profiles import ProfileConfig, ensure_metadata_profiles_available
from ..services.month_processor import MonthProcessor

console = Console()
metadata_app = typer.Typer(help="Metadata allocation commands")


@metadata_app.command("run")
def run_metadata_allocation(
    config: str = typer.Option(..., help="Path to metadata configuration YAML file"),
    month: str = typer.Option(None, help="Specific month (YYYY-MM) - optional override"),
    provider: str = typer.Option(None, help="Specific provider - optional override"),
    debug: bool = typer.Option(False, help="Enable debug logging for troubleshooting"),
    force: bool = typer.Option(False, "--force", help="Force reprocessing: deletes existing metadata data and reprocesses"),
):
    """
    Process metadata allocation for billing data.
    
    Reads from k8s/generate stage S3 output and writes to metadata stage S3 output.
    Processes one month at a time for memory efficiency.
    Uses V1 hybrid approach with deterministic allocation.
    
    Metadata profiles are automatically downloaded from S3:
    s3://bucket/czbillgen/metadata_profiles/metadata_profiles.yaml
    
    Example:
        czbillgen metadata run --config metadata_config.yaml
        czbillgen metadata run --config metadata_config.yaml --month 2024-01
        czbillgen metadata run --config metadata_config.yaml --provider AWS
        czbillgen metadata run --config metadata_config.yaml --debug
    """
    try:
        # FAIL FAST: Validate AWS credentials before any work
        from services.environment_service import EnvironmentService
        env_service = EnvironmentService()
        env_service.validate_aws_credentials_and_access()
        
    except ValueError as e:
        console.print(f"❌ {str(e)}")
        raise typer.Exit(1)
    
    console.print("🚀 [bold green]Metadata Allocation Starting[/bold green]")
    
    # Configure debug logging if requested
    if debug:
        logging.basicConfig(level=logging.DEBUG)
        console.print("🔍 [yellow]Debug logging enabled[/yellow]")
    
    try:
        # Load configuration
        metadata_config = MetadataConfig.from_yaml(config)
        
        # Validate configuration
        config_errors = metadata_config.validate()
        if config_errors:
            console.print("❌ [bold red]Configuration validation failed:[/bold red]")
            for error in config_errors:
                console.print(f"  • {error}")
            raise typer.Exit(1)
        
        # Check for existing success marker
        if _check_and_handle_existing_metadata_data(metadata_config.dataset_name, force):
            raise typer.Exit(0)
        
        console.print(f"📊 Dataset: {metadata_config.dataset_name}")
        console.print(f"🌍 Geographic Markets: {', '.join(metadata_config.majority_regions.keys())}")
        console.print(f"🏗️  Environment: {metadata_config.majority_environment}")
        console.print(f"📦 Base allocation: {metadata_config.base_allocation}")
        
        # Load profiles from S3 with auto-download
        profile_config = ensure_metadata_profiles_available()
        if profile_config is None:
            raise typer.Exit(1)
        
        console.print(f"📋 Profiles loaded from S3 (cached locally)")
        
        # Validate profile key collisions
        collision_errors = profile_config.validate_key_collision()
        if collision_errors:
            console.print("❌ [bold red]Profile key collision errors:[/bold red]")
            for error in collision_errors:
                console.print(f"  • {error}")
            raise typer.Exit(1)
        
        # Initialize month processor
        month_processor = MonthProcessor(metadata_config, profile_config, console, force)
        
        # Process all months
        processing_stats = month_processor.process_all_months(month, provider)
        
        # Print final summary
        month_processor.print_final_summary()
        
        # Exit with appropriate code
        if processing_stats['failed_months'] == 0 and processing_stats['processed_months'] > 0:
            # Success
            pass
        elif processing_stats['processed_months'] > 0:
            # Partial success
            raise typer.Exit(1)
        else:
            # No data processed
            raise typer.Exit(1)
        
    except FileNotFoundError as e:
        console.print(f"❌ [bold red]File not found:[/bold red] {str(e)}")
        raise typer.Exit(1)
    except ValueError as e:
        console.print(f"❌ [bold red]Configuration error:[/bold red] {str(e)}")
        raise typer.Exit(1)
    except Exception as e:
        console.print(f"❌ [bold red]Error:[/bold red] {str(e)}")
        if debug:
            import traceback
            console.print(f"[red]{traceback.format_exc()}[/red]")
        raise typer.Exit(1)


@metadata_app.command("validate")
def validate_metadata_config(
    config: str = typer.Option(..., help="Path to metadata configuration YAML file"),
):
    """Validate metadata configuration and profiles."""
    console.print("🔍 [bold blue]Metadata Configuration Validation[/bold blue]")
    
    try:
        # Load and validate configuration
        metadata_config = MetadataConfig.from_yaml(config)
        
        config_errors = metadata_config.validate()
        if config_errors:
            console.print("❌ [bold red]Configuration validation failed:[/bold red]")
            for error in config_errors:
                console.print(f"  • {error}")
            raise typer.Exit(1)
        
        console.print("✅ [green]Configuration validation passed[/green]")
        
        # Load and validate profiles from S3
        profile_config = ensure_metadata_profiles_available()
        if profile_config is None:
            raise typer.Exit(1)
        
        # Validate profile key collisions
        collision_errors = profile_config.validate_key_collision()
        if collision_errors:
            console.print("❌ [bold red]Profile key collision errors:[/bold red]")
            for error in collision_errors:
                console.print(f"  • {error}")
            raise typer.Exit(1)
        
        console.print("✅ [green]Profile validation passed[/green]")
        
        # Show summary
        console.print(f"\n📋 [cyan]Configuration Summary:[/cyan]")
        console.print(f"  Dataset: {metadata_config.dataset_name}")
        console.print(f"  Geographic Markets: {', '.join(metadata_config.majority_regions.keys())}")
        console.print(f"  Environment: {metadata_config.majority_environment}")
        console.print(f"  Base allocation: {metadata_config.base_allocation}")
        
        console.print(f"\n📋 [cyan]Geographic Market Distribution:[/cyan]")
        for region, config_info in metadata_config.majority_regions.items():
            console.print(f"  {region}: {config_info.weight:.1%} (majority: {config_info.majority})")
        
        console.print(f"\n📋 [cyan]Profile Summary:[/cyan]")
        console.print(f"  Environment key variants: {profile_config.environments.key_variants}")
        console.print(f"  Feature key variants: {profile_config.features.key_variants}")
        console.print(f"  Geographic markets: {', '.join(profile_config.regions.values.keys())}")
        
        if profile_config.cost_centers:
            console.print(f"  Cost center key variants: {profile_config.cost_centers.key_variants}")
        if profile_config.teams:
            console.print(f"  Team key variants: {profile_config.teams.key_variants}")
        
        console.print("\n✅ [bold green]All validation passed![/bold green]")
        
    except Exception as e:
        console.print(f"❌ [bold red]Error:[/bold red] {str(e)}")
        raise typer.Exit(1)


def _check_and_handle_existing_metadata_data(dataset_name: str, force: bool) -> bool:
    """
    Check for existing metadata success marker and handle force flag logic.
    
    Args:
        dataset_name: Dataset name to check
        force: Whether force flag was provided
        
    Returns:
        True if should exit (data exists and not forced), False if should continue
    """
    if _metadata_success_marker_exists(dataset_name):
        if not force:
            console.print(f"✅ Metadata stage already completed for dataset '{dataset_name}'. Use --force to reprocess.")
            return True
        
        # Force flag provided - confirm and delete existing data
        console.print(f"⚠️  This will delete ALL existing metadata data for dataset '{dataset_name}' and reprocess.")
        
        # Confirmation prompt
        confirm = typer.confirm("❓ Continue?")
        if not confirm:
            console.print("Operation cancelled.")
            return True
        
        # Delete existing metadata data
        console.print(f"🗑️  Deleting existing metadata data for dataset '{dataset_name}'...")
        _delete_metadata_stage_data(dataset_name)
        console.print(f"✅ Existing metadata data deleted for dataset '{dataset_name}'")
    
    return False


def _metadata_success_marker_exists(dataset_name: str) -> bool:
    """
    Check if metadata stage success marker exists for a dataset.
    
    Args:
        dataset_name: Dataset name to check
        
    Returns:
        True if success marker exists, False otherwise
    """
    try:
        from services.s3_data_service import S3DataService
        from services.success_marker_service import SuccessMarkerService
        
        s3_service = S3DataService()
        success_marker_service = SuccessMarkerService(s3_service)
        
        return success_marker_service.check_success_marker_exists(dataset_name, "metadata")
        
    except Exception:
        # If any error occurs, assume marker doesn't exist
        return False


def _delete_metadata_stage_data(dataset_name: str) -> None:
    """
    Delete all metadata stage data for a dataset.
    
    Deletes entire metadata folder: s3://bucket/czbillgen/datasets/{dataset_name}/metadata/
    This ensures no mixed configuration data remains.
    
    Args:
        dataset_name: Dataset name to delete data for
    """
    try:
        from services.s3_data_service import S3DataService
        s3_service = S3DataService()
        
        stage_prefix = f"czbillgen/datasets/{dataset_name}/metadata/"
        
        # List all objects in metadata stage folder
        s3_client = s3_service.s3_client
        bucket = s3_service.bucket
        
        paginator = s3_client.get_paginator('list_objects_v2')
        page_iterator = paginator.paginate(
            Bucket=bucket,
            Prefix=stage_prefix
        )
        
        objects_to_delete = []
        for page in page_iterator:
            if 'Contents' in page:
                objects_to_delete.extend([{'Key': obj['Key']} for obj in page['Contents']])
        
        if objects_to_delete:
            # Delete objects in batches (S3 delete_objects limit is 1000)
            for i in range(0, len(objects_to_delete), 1000):
                batch = objects_to_delete[i:i+1000]
                s3_client.delete_objects(
                    Bucket=bucket,
                    Delete={'Objects': batch}
                )
            
            console.print(f"🗑️  Deleted {len(objects_to_delete)} objects from metadata stage")
        else:
            console.print("📂 No existing metadata data found to delete")
        
        # Also delete success marker using standardized service
        from services.success_marker_service import SuccessMarkerService
        success_marker_service = SuccessMarkerService(s3_service)
        success_marker_service.delete_success_marker(dataset_name, "metadata")
            
    except Exception as e:
        console.print(f"❌ Failed to delete metadata stage data: {e}")
        raise typer.Exit(1)