"""
Connection orchestrator service implementation.

Handles connection validation, auto-creation, and recreation operations
across organizations with proper error handling and state management.
"""

from typing import Dict, List, Any, Optional
from ..interfaces import ConnectionOrchestratorInterface
from ..models import ConnectionValidationResult, UploadConfig, ValidationStatus


class ConnectionOrchestrator(ConnectionOrchestratorInterface):
    """
    Implementation of connection orchestration operations.
    
    Centralized connection management for CloudZero billing connections
    across multiple organizations with auto-creation and recreation capabilities.
    """
    
    def __init__(self):
        """Initialize connection orchestrator."""
        pass
    
    def ensure_connections_exist(
        self,
        organization: str,
        providers: List[str],
        s3_config: Dict[str, str]
    ) -> ConnectionValidationResult:
        """
        Ensure all required connections exist for an organization.
        
        Args:
            organization: Organization name
            providers: List of provider names requiring connections
            s3_config: S3 configuration for connection creation
            
        Returns:
            ConnectionValidationResult with validation and creation outcomes
        """
        if not providers:
            return ConnectionValidationResult(
                organization=organization,
                providers=[],
                status=ValidationStatus.SUCCESS
            )
        
        try:
            # Get organization API key and connection manager
            api_key = self.get_organization_api_key(organization)
            conn_manager = self._create_connection_manager(api_key)
            
            print(f"   🔍 Ensuring connections for {len(providers)} providers...")
            
            # Check existing connections
            conn_status = conn_manager.validate_connections_exist(providers)
            missing_providers = [p for p, exists in conn_status.items() if not exists]
            
            if missing_providers:
                print(f"   ⚙️  Auto-creating {len(missing_providers)} missing connections...")
                
                # Auto-create missing connections
                conn_results = conn_manager.ensure_all_connections(providers, s3_config)
                
                print(f"   ✅ {organization}: All connections ready ({len(providers)} providers)")
                return ConnectionValidationResult(
                    organization=organization,
                    providers=providers,
                    status=ValidationStatus.SUCCESS,
                    auto_created_connections=missing_providers
                )
            else:
                print(f"   ✅ {organization}: All connections validated ({len(providers)} providers)")
                return ConnectionValidationResult(
                    organization=organization,
                    providers=providers,
                    status=ValidationStatus.SUCCESS
                )
                
        except Exception as e:
            print(f"   ❌ Exception ensuring connections for {organization}: {str(e)}")
            return ConnectionValidationResult(
                organization=organization,
                providers=providers,
                status=ValidationStatus.FAILED,
                error_message=str(e)
            )
    
    def validate_connection_status(
        self,
        organization: str,
        providers: List[str]
    ) -> ConnectionValidationResult:
        """
        Validate connection status without creating new connections.
        
        Args:
            organization: Organization name
            providers: List of provider names to validate
            
        Returns:
            ConnectionValidationResult with validation status
        """
        try:
            api_key = self.get_organization_api_key(organization)
            conn_manager = self._create_connection_manager(api_key)
            
            # Check existing connections only
            conn_status = conn_manager.validate_connections_exist(providers)
            missing_providers = [p for p, exists in conn_status.items() if not exists]
            
            if missing_providers:
                return ConnectionValidationResult(
                    organization=organization,
                    providers=providers,
                    status=ValidationStatus.FAILED,
                    missing_providers=missing_providers,
                    error_message=f"Missing connections for providers: {missing_providers}"
                )
            else:
                return ConnectionValidationResult(
                    organization=organization,
                    providers=providers,
                    status=ValidationStatus.SUCCESS
                )
                
        except Exception as e:
            return ConnectionValidationResult(
                organization=organization,
                providers=providers,
                status=ValidationStatus.FAILED,
                error_message=str(e)
            )
    
    def recreate_organization_connections(
        self,
        organization: str,
        providers: List[str],
        s3_config: Dict[str, str],
        dry_run: bool = False,
        delete_data: bool = False,
        connection_suffix: Optional[str] = None
    ) -> Dict[str, Any]:
        """
        Recreate all connections for an organization.

        Phase 2 Modes:
        - Mode 2 (delete_data=False): Delete and recreate connections, preserve S3 data
        - Mode 3 (delete_data=True): Delete connections and S3 data, recreate connections

        Args:
            organization: Organization name
            providers: List of provider names
            s3_config: S3 configuration for new connections
            dry_run: If True, only show what would be done
            delete_data: If True, delete S3 data along with connections (Mode 3)
            connection_suffix: Optional suffix for connection naming

        Returns:
            Recreation result with deleted and created connection details
        """
        try:
            if dry_run:
                return self._simulate_connection_recreation(organization, providers, s3_config, connection_suffix=connection_suffix)
            else:
                return self._execute_connection_recreation(organization, providers, s3_config, delete_data=delete_data, connection_suffix=connection_suffix)

        except Exception as e:
            print(f"   ❌ Connection recreation failed for {organization}: {str(e)}")
            return {
                "status": "failed",
                "organization": organization,
                "error_message": str(e),
                "deleted_connections": [],
                "created_connections": [],
                "deleted_folders": []
            }
    
    def validate_api_credentials(self, organization: str) -> bool:
        """
        Validate API credentials for an organization.
        
        Args:
            organization: Organization name
            
        Returns:
            True if credentials are valid, False otherwise
        """
        try:
            api_key = self.get_organization_api_key(organization)
            conn_manager = self._create_connection_manager(api_key)
            
            # Try to validate connections exist (this will test API access)
            test_result = conn_manager.validate_connections_exist([])  # Empty list just tests API access
            return True  # If no exception, credentials are valid
            
        except Exception:
            return False
    
    def get_organization_api_key(self, organization: str) -> str:
        """
        Get API key for an organization.
        
        Args:
            organization: Organization name
            
        Returns:
            API key for the organization
            
        Raises:
            ConnectionOrchestratorError: If no API key found
        """
        from ..api.connection_manager import get_org_api_key
        return get_org_api_key(organization)
    
    def list_organization_connections(
        self,
        organization: str,
        providers: List[str] = None
    ) -> Dict[str, List[Dict[str, Any]]]:
        """
        List existing connections for an organization.
        
        Args:
            organization: Organization name
            providers: Optional list to filter by providers
            
        Returns:
            Dict mapping provider names to list of connection details
        """
        try:
            api_key = self.get_organization_api_key(organization)
            conn_manager = self._create_connection_manager(api_key)
            
            # Get all connections if no providers specified
            if providers is None:
                providers = ["AWS", "Azure", "GCP"]  # Default providers
            
            connections_by_provider = {}
            for provider in providers:
                connection = conn_manager.api.find_enabled_bucket_connection(provider)
                if connection:
                    connections_by_provider[provider] = [connection]
                else:
                    connections_by_provider[provider] = []
            
            return connections_by_provider
            
        except Exception as e:
            print(f"Failed to list connections for {organization}: {str(e)}")
            return {}
    
    def _create_connection_manager(self, api_key: str):
        """Create connection manager with API key."""
        from ..api.connection_manager import ConnectionManager
        return ConnectionManager(api_key)
    
    def _simulate_connection_recreation(
        self,
        organization: str,
        providers: List[str],
        s3_config: Dict[str, str],
        connection_suffix: Optional[str] = None
    ) -> Dict[str, Any]:
        """Simulate connection recreation for dry run."""
        # Get existing connections
        existing_connections = self.list_organization_connections(organization, providers)
        
        deleted_connections = []
        for provider, connections in existing_connections.items():
            for conn in connections:
                deleted_connections.append({
                    "provider": provider,
                    "connection_id": conn.get("id", f"conn_{provider}"),
                    "connection_name": conn.get("name", f"{provider} Connection")
                })
        
        created_connections = []
        for provider in providers:
            created_connections.append({
                "provider": provider,
                "connection_name": f"{provider.lower()}_bc_0001_simulation"
            })
        
        return {
            "status": "success",
            "organization": organization,
            "deleted_connections": deleted_connections,
            "created_connections": created_connections,
            "deleted_folders": [],  # Would simulate S3 folder deletion
            "dry_run": True
        }
    
    def _execute_connection_recreation(
        self,
        organization: str,
        providers: List[str],
        s3_config: Dict[str, str],
        delete_data: bool = False,
        connection_suffix: Optional[str] = None
    ) -> Dict[str, Any]:
        """
        Execute actual connection recreation using Phase 2 services.

        Phase 2 Modes:
        - Mode 2 (delete_data=False): Delete/recreate connections, preserve S3 data
        - Mode 3 (delete_data=True): Delete connections + S3 data, recreate connections

        Args:
            organization: Organization name
            providers: List of provider names
            s3_config: S3 configuration
            delete_data: Whether to delete S3 data (Mode 3)
            connection_suffix: Optional suffix for connection naming

        Returns:
            Recreation result dictionary
        """
        mode = "Mode 3" if delete_data else "Mode 2"
        print(f"   🔄 {mode}: Executing connection recreation for {organization}...")

        try:
            # Initialize Phase 2 services
            from .connection_lifecycle_manager import ConnectionLifecycleManager, ConnectionConfig
            from .data_lifecycle_manager import DataLifecycleManager
            from ..api.client import CloudZeroAPI
            from .secrets_resolver import SecretsResolver

            # Get API token for organization
            secrets_resolver = SecretsResolver(region=s3_config.get("region", "us-east-1"))
            api_token = secrets_resolver.get_org_api_key(organization)
            api_client = CloudZeroAPI(api_token)

            # Initialize Phase 2 services
            connection_lifecycle = ConnectionLifecycleManager(api_client)
            data_lifecycle = DataLifecycleManager(
                s3_bucket=s3_config["bucket_name"],
                s3_root_folder=s3_config.get("root_folder", "piedpiper-custom-billing")
            )

            deleted_connections = []
            created_connections = []
            deleted_folders = []

            # Phase 1: Delete existing connections for each provider
            print(f"   Phase 1: Deleting connections for {len(providers)} providers")
            for provider in providers:
                try:
                    connection_lifecycle.delete_connection(organization, provider)
                    deleted_connections.append({"provider": provider, "action": "deleted"})
                except Exception as e:
                    print(f"   ⚠️  Failed to delete {provider} connection: {str(e)}")

            # Phase 2: Delete S3 data (Mode 3 only)
            if delete_data:
                print(f"   Phase 2 (Mode 3): Deleting S3 data for {len(providers)} providers")
                for provider in providers:
                    try:
                        objects_deleted = data_lifecycle.delete_data(organization, provider)
                        deleted_folders.append({
                            "provider": provider,
                            "objects": objects_deleted
                        })
                    except Exception as e:
                        print(f"   ⚠️  Failed to delete {provider} data: {str(e)}")
            else:
                print(f"   Phase 2 (Mode 2): Preserving S3 data")

            # Phase 3: Recreate connections
            print(f"   Phase 3: Recreating connections for {len(providers)} providers")
            for provider in providers:
                try:
                    from src.services.environment_service import EnvironmentService
                    env_service = EnvironmentService()

                    config = ConnectionConfig(
                        org=organization,
                        provider=provider,
                        suffix=connection_suffix,
                        s3_bucket=s3_config["bucket_name"],
                        s3_root_folder=s3_config.get("root_folder", "piedpiper-custom-billing"),
                        s3_org_folder=s3_config.get("org_folder", organization),
                        role_arn=env_service.require("AWS_IAM_ROLE_ARN"),
                        external_id=env_service.require("AWS_IAM_EXTERNAL_ID")
                    )

                    connection_id = connection_lifecycle.create_connection(config)
                    created_connections.append({
                        "provider": provider,
                        "connection_id": connection_id
                    })
                except Exception as e:
                    print(f"   ⚠️  Failed to recreate {provider} connection: {str(e)}")

            # Determine overall status
            status = "success"
            error_message = None
            if not created_connections:
                status = "failed"
                error_message = "No connections were successfully recreated"
            elif len(created_connections) < len(providers):
                status = "partial"
                error_message = f"Only {len(created_connections)}/{len(providers)} connections recreated"

            return {
                "status": status,
                "organization": organization,
                "deleted_connections": deleted_connections,
                "created_connections": created_connections,
                "deleted_folders": deleted_folders,
                "error_message": error_message,
                "mode": mode
            }

        except Exception as e:
            print(f"   ❌ Recreation execution failed: {str(e)}")
            return {
                "status": "failed",
                "organization": organization,
                "error_message": str(e),
                "deleted_connections": [],
                "created_connections": [],
                "deleted_folders": [],
                "mode": mode
            }