"""
CloudZero billing connection management CLI for czbillgen upload.

Provides comprehensive connection management capabilities including:
- List all billing connections
- Test API connectivity  
- Create connections for providers
- Delete individual or bulk connections
- CostFormation YAML output

Based on cz-demo load connections command patterns.
"""

import os
import re
from pathlib import Path
from typing import Optional

import typer

from src.services.environment_service import EnvironmentService
from src.upload.api import CloudZeroAPI, create_cloudzero_connection
from src.upload.api.connection_manager import get_org_api_key


app = typer.Typer(help="Manage CloudZero billing connections")


@app.command("list")
def list_connections(
    org: str = typer.Option(..., "--org", help="Organization name (must match config)"),
    cf: bool = typer.Option(False, "--cf", help="Output CostFormation YAML for bucket connections")
) -> None:
    """
    List all billing connections for the specified organization.
    
    Examples:
      czbillgen upload connections list --org DemoTest
      czbillgen upload connections list --org DemoTest --cf  # CostFormation YAML output
    """
    env_service = EnvironmentService()
    
    # Get org-specific API key
    try:
        org_api_key = get_org_api_key(org)
        api = CloudZeroAPI(org_api_key)
    except ValueError as e:
        typer.echo(f"❌ CloudZero API key error for organization '{org}': {e}")
        raise typer.Exit(1)
    
    # Show organization context
    if not cf:
        typer.echo("🔗 CloudZero Connection Management")
        api.print_organization_context()
        typer.echo("📋 Listing all billing connections...")
    
    try:
        connections = api.list_billing_connections()
        if not connections:
            if not cf:
                typer.echo("No billing connections found")
        else:
            if cf:
                # CostFormation YAML output
                bucket_pattern = re.compile(r'_bc_\d{4}$')
                bucket_connections = []
                
                for conn in connections:
                    conn_name = conn.get('name', 'Unknown')
                    if bucket_pattern.search(conn_name):
                        bucket_connections.append(conn)
                
                if bucket_connections:
                    # Output CostFormation YAML structure
                    typer.echo("BillingConnectionGroups:")
                    typer.echo("  Name: Billing Connection Groups")
                    typer.echo("  DefaultValue: Other Connections")
                    typer.echo("  Child: CloudProvider")
                    typer.echo("  Source: PayerAccount")
                    typer.echo("  Rules:")
                    typer.echo("    - Type: Group")
                    typer.echo("      Name: Bucket Connections")
                    typer.echo("      Conditions:")
                    typer.echo("        - Equals:")
                    
                    for conn in bucket_connections:
                        conn_id = conn.get('id', 'Unknown')
                        conn_name = conn.get('name', 'Unknown')
                        conn_provider = conn.get('cloud_provider', 'Unknown')
                        status = "Enabled" if conn.get("is_enabled", False) else "Disabled"
                        typer.echo(f"            - {conn_id}  # {conn_name} ({conn_provider}) - {status}")
            else:
                # Regular formatted output
                for conn in connections:
                    status = "✅" if conn.get("is_enabled", False) else "❌"
                    conn_id = conn.get('id', 'Unknown')
                    conn_name = conn.get('name', 'Unknown')
                    conn_provider = conn.get('cloud_provider', 'Unknown')
                    typer.echo(f"{status} {conn_name} ({conn_provider}) [ID: {conn_id}]")
    except Exception as e:
        if not cf:
            typer.echo(f"❌ Failed to list connections: {e}")
        raise typer.Exit(1)


@app.command("test")
def test_connection(
    org: str = typer.Option(..., "--org", help="Organization name (must match config)")
) -> None:
    """
    Test CloudZero API connection for the specified organization.
    
    Example:
      czbillgen upload connections test --org DemoTest
    """
    # Get org-specific API key
    try:
        org_api_key = get_org_api_key(org)
        api = CloudZeroAPI(org_api_key)
    except ValueError as e:
        typer.echo(f"❌ CloudZero API key error for organization '{org}': {e}")
        raise typer.Exit(1)
    
    # Show organization context
    typer.echo("🔗 CloudZero Connection Management")
    api.print_organization_context()
    
    typer.echo("🔍 Testing CloudZero API connection...")
    try:
        connections = api.list_billing_connections()
        typer.echo(f"✅ CloudZero API connection successful ({len(connections)} connections found)")
    except Exception as e:
        typer.echo(f"❌ CloudZero API connection failed: {e}")
        raise typer.Exit(1)


@app.command("create")
def create_connection(
    org: str = typer.Option(..., "--org", help="Organization name (must match config)"),
    provider: str = typer.Option(..., "--provider", help="Provider to create connection for (AWS, Azure, GCP)"),
    config: str = typer.Option(..., "--config", help="S3 config file for connection creation")
) -> None:
    """
    Create a billing connection for the specified provider and organization.
    
    Example:
      czbillgen upload connections create --org DemoTest --provider AWS --config configs/upload/upload.config.yaml
    """
    env_service = EnvironmentService()
    
    # Get org-specific API key
    try:
        org_api_key = get_org_api_key(org)
        api = CloudZeroAPI(org_api_key)
    except ValueError as e:
        typer.echo(f"❌ CloudZero API key error for organization '{org}': {e}")
        raise typer.Exit(1)
    
    # Show organization context
    typer.echo("🔗 CloudZero Connection Management")
    api.print_organization_context()
    
    typer.echo(f"🔗 Creating connection for {provider} in organization {org}...")
    try:
        # Validate AWS IAM credentials are available
        aws_iam_role = env_service.get("AWS_IAM_ROLE_ARN")
        aws_iam_external_id = env_service.get("AWS_IAM_EXTERNAL_ID")
        
        if not aws_iam_role or not aws_iam_external_id:
            missing = []
            if not aws_iam_role:
                missing.append("AWS_IAM_ROLE_ARN")
            if not aws_iam_external_id:
                missing.append("AWS_IAM_EXTERNAL_ID")
            typer.echo(f"❌ Missing required AWS IAM configuration: {', '.join(missing)}")
            typer.echo("Please set these environment variables in your ~/.czbillgen/.env file")
            raise typer.Exit(1)
        
        # Load S3 config
        from upload.s3.config import S3Config
        s3_config = S3Config.from_config_file(config, upload_type="generated")
        
        # Create connection
        connection = create_cloudzero_connection(
            provider=provider,
            s3_bucket_name=s3_config.bucket,
            s3_root_folder=s3_config.root_folder,
            s3_org_folder=org,  # Use org name as folder
            role_arn=aws_iam_role,
            external_id=aws_iam_external_id
        )
        
        result = api.create_billing_connection(connection)
        typer.echo(f"✅ Connection created: {connection.name}")
        
    except Exception as e:
        typer.echo(f"❌ Failed to create connection: {e}")
        raise typer.Exit(1)


@app.command("delete")
def delete_connection(
    org: str = typer.Option(..., "--org", help="Organization name (must match config)"),
    name: str = typer.Option(..., "--name", help="Connection name to delete")
) -> None:
    """
    Delete a specific billing connection by name.
    
    Example:
      czbillgen upload connections delete --org DemoTest --name aws_bc_0001
    """
    # Get org-specific API key
    try:
        org_api_key = get_org_api_key(org)
        api = CloudZeroAPI(org_api_key)
    except ValueError as e:
        typer.echo(f"❌ CloudZero API key error for organization '{org}': {e}")
        raise typer.Exit(1)
    
    # Show organization context
    typer.echo("🔗 CloudZero Connection Management")
    api.print_organization_context()
    
    typer.echo(f"🗑️  Deleting connection: {name}")
    try:
        # Find connection by name
        connections = api.list_billing_connections()
        target_connection = None
        for conn in connections:
            if conn.get("name") == name:
                target_connection = conn
                break
        
        if not target_connection:
            typer.echo(f"❌ Connection not found: {name}")
            raise typer.Exit(1)
        
        # Delete connection
        success = api.delete_billing_connection(target_connection["id"])
        if success:
            typer.echo(f"✅ Connection deleted: {name}")
        else:
            typer.echo(f"❌ Failed to delete connection: {name}")
            raise typer.Exit(1)
            
    except Exception as e:
        typer.echo(f"❌ Failed to delete connection: {e}")
        raise typer.Exit(1)


@app.command("delete-all-non-bucket")  
def delete_all_non_bucket(
    org: str = typer.Option(..., "--org", help="Organization name (must match config)"),
    force: bool = typer.Option(False, "--force", help="Skip confirmation prompt"),
    config: Optional[str] = typer.Option(None, "--config", help="S3 config file for provider filtering")
) -> None:
    """
    Delete all non-bucket connections (not ending with _bc_XXXX pattern).
    
    For PiedPiper org: only deletes connections ending with '-CUSTOM-BILLING' 
    or starting with '<provider>-<number>'.
    
    Examples:
      czbillgen upload connections delete-all-non-bucket --org DemoTest
      czbillgen upload connections delete-all-non-bucket --org DemoTest --force
      czbillgen upload connections delete-all-non-bucket --org PiedPiper --config upload.config.yaml
    """
    # Get org-specific API key
    try:
        org_api_key = get_org_api_key(org)
        api = CloudZeroAPI(org_api_key)
    except ValueError as e:
        typer.echo(f"❌ CloudZero API key error for organization '{org}': {e}")
        raise typer.Exit(1)
    
    # Show organization context
    typer.echo("🔗 CloudZero Connection Management")
    api.print_organization_context()
    
    typer.echo(f"🗑️  Finding non-bucket connections for organization: {org}")
    try:
        # Get all connections
        connections = api.list_billing_connections()
        
        # Filter for non-bucket connections (not ending with _bc_XXXX pattern)
        bucket_pattern = re.compile(r'_bc_\d{4}$')
        non_bucket_connections = []
        
        # Special case for PiedPiper org
        is_piedpiper = org.upper() == "PIEDPIPER"
        
        if is_piedpiper:
            typer.echo("🔍 Applying PiedPiper-specific filtering rules...")
            
            # Get configured providers from S3 config if available
            configured_providers = []
            if config:
                try:
                    from upload.s3.config import S3Config
                    s3_config = S3Config.from_config_file(config, upload_type="generated")
                    # Would need to extract providers from config - placeholder for now
                    configured_providers = ["AWS", "Azure", "GCP"]  # Default providers
                except Exception:
                    pass  # Continue without provider filtering if config unavailable
            
            # PiedPiper filtering: only connections ending in "-CUSTOM-BILLING" 
            # or starting with "<provider>-<number>"
            custom_billing_pattern = re.compile(r'-CUSTOM-BILLING$')
            
            for conn in connections:
                conn_name = conn.get("name", "")
                if bucket_pattern.search(conn_name):
                    continue  # Skip bucket connections
                
                # Check if ends with "-CUSTOM-BILLING"
                if custom_billing_pattern.search(conn_name):
                    non_bucket_connections.append(conn)
                    continue
                
                # Check if starts with configured provider + dash + number
                if configured_providers:
                    for provider in configured_providers:
                        provider_pattern = re.compile(f'^{re.escape(provider.lower())}-\\d+', re.IGNORECASE)
                        if provider_pattern.match(conn_name):
                            non_bucket_connections.append(conn)
                            break
        else:
            # Standard filtering for all other orgs
            for conn in connections:
                conn_name = conn.get("name", "")
                if not bucket_pattern.search(conn_name):
                    non_bucket_connections.append(conn)
        
        if not non_bucket_connections:
            typer.echo("✅ No non-bucket connections found to delete")
            return
        
        # Show what would be deleted
        if is_piedpiper:
            typer.echo(f"📋 Found {len(non_bucket_connections)} PiedPiper-filtered connection(s):")
            typer.echo("   (Only connections ending in '-CUSTOM-BILLING' or starting with '<provider>-<number>')")
        else:
            typer.echo(f"📋 Found {len(non_bucket_connections)} non-bucket connection(s):")
        
        for conn in non_bucket_connections:
            conn_type = conn.get("type", "unknown")
            typer.echo(f"  • {conn['name']} (type: {conn_type})")
        
        # Confirmation (unless --force is used)
        if not force:
            if is_piedpiper:
                typer.echo(f"\n⚠️  This will permanently delete {len(non_bucket_connections)} connection(s) using PiedPiper-specific rules.")
                typer.echo("   Only connections ending in '-CUSTOM-BILLING' or starting with '<provider>-<number>' will be deleted.")
            else:
                typer.echo(f"\n⚠️  This will permanently delete {len(non_bucket_connections)} connection(s).")
            confirm = typer.confirm("Are you sure you want to continue?")
            if not confirm:
                typer.echo("❌ Operation cancelled")
                return
        
        # Delete connections
        typer.echo(f"\n🗑️  Deleting {len(non_bucket_connections)} non-bucket connections...")
        deleted_count = 0
        failed_count = 0
        
        for conn in non_bucket_connections:
            conn_name = conn.get("name", "unknown")
            try:
                success = api.delete_billing_connection(conn["id"])
                if success:
                    typer.echo(f"  ✅ Deleted: {conn_name}")
                    deleted_count += 1
                else:
                    typer.echo(f"  ❌ Failed to delete: {conn_name}")
                    failed_count += 1
            except Exception as e:
                typer.echo(f"  ❌ Error deleting {conn_name}: {str(e)}")
                failed_count += 1
        
        # Final results
        typer.echo(f"\n📊 Deletion Results:")
        typer.echo(f"  ✅ Successfully deleted: {deleted_count}")
        if failed_count > 0:
            typer.echo(f"  ❌ Failed to delete: {failed_count}")
            raise typer.Exit(1)
        else:
            typer.echo(f"🎉 All non-bucket connections deleted successfully!")
            
    except Exception as e:
        typer.echo(f"❌ Failed to delete non-bucket connections: {e}")
        raise typer.Exit(1)