"""
Thin upload workflow coordinator.

Replaces S3UploadOrchestrator god class with focused coordination logic.
Delegates all business logic to specialized services while maintaining
clean interface for CLI integration.
"""

import os
from typing import Dict, Any
from ..models import UploadConfig, WorkflowResult
from .upload_workflow_methods import UploadWorkflowMethods


class UploadWorkflowCoordinator:
    """
    Thin coordinator for upload workflows.
    
    Replaces 1,140-line S3UploadOrchestrator with focused coordination.
    All business logic is delegated to specialized services following
    Single Responsibility Principle.
    
    Target: <200 lines total (currently ~150 lines)
    """
    
    def __init__(
        self,
        validation_service,
        data_processing_service, 
        s3_upload_service,
        connection_orchestrator
    ):
        """
        Initialize coordinator with injected services.
        
        Args:
            validation_service: Upload validation service
            data_processing_service: Data processing service  
            s3_upload_service: S3 upload service
            connection_orchestrator: Connection orchestration service
        """
        self.validation_service = validation_service
        self.data_processing_service = data_processing_service
        self.s3_upload_service = s3_upload_service
        self.connection_orchestrator = connection_orchestrator
        
        # Initialize workflow methods with injected services
        self.workflow_methods = UploadWorkflowMethods(
            validation_service,
            data_processing_service,
            s3_upload_service, 
            connection_orchestrator
        )
    
    def upload_dataset(self, config: UploadConfig, dry_run: bool = False) -> WorkflowResult:
        """
        Upload generated dataset to all configured organizations.
        
        Thin coordination method that delegates to workflow methods.
        Handles both regular upload and append mode operations.
        
        Args:
            config: Upload configuration
            dry_run: Whether to perform dry run validation only
            
        Returns:
            WorkflowResult with upload outcomes
        """
        if config.is_append_mode():
            # Use append workflow for incremental uploads
            if dry_run:
                print(f"🧪 Validating append operation for dataset: {config.dataset_name}")
            else:
                print(f"🔄 Starting append upload for dataset: {config.dataset_name}")
                print(f"🏢 Organizations: {len(config.organizations)}")
            
            return self._execute_append_workflow(config, dry_run)
        else:
            # Use regular upload workflow
            if dry_run:
                print(f"🧪 Validating dataset: {config.dataset_name}")
            else:
                print(f"🚀 Starting upload for dataset: {config.dataset_name}")
                print(f"🏢 Organizations: {len(config.organizations)}")
            
            return self.workflow_methods.execute_upload_workflow(config, dry_run)
    
    def upload_adhoc_csv(self, config: UploadConfig, dry_run: bool = False) -> WorkflowResult:
        """
        Upload ad-hoc CSV dataset to all configured organizations.
        
        Thin coordination method for ad-hoc uploads.
        Replaces 135-line upload_adhoc_to_orgs method.
        
        Args:
            config: Upload configuration with ad-hoc CSV details
            dry_run: Whether to perform dry run validation only
            
        Returns:
            WorkflowResult with upload outcomes
        """
        print(f"🚀 Starting ad-hoc upload for CSV: {config.adhoc_csv_path}")
        print(f"🏢 Organizations: {len(config.organizations)}")
        
        if dry_run:
            print("🧪 DRY RUN MODE - No files will be uploaded")
        
        return self.workflow_methods.execute_adhoc_upload_workflow(config, dry_run)
    
    def recreate_connections_and_upload(self, config: UploadConfig, delete_data: bool = False) -> WorkflowResult:
        """
        Execute connection recreation followed by upload.

        Thin coordination method for recreation workflow.
        Replaces 80+ line recreate_and_upload method.

        Phase 2 Modes:
        - Mode 2 (delete_data=False): Recreate connections, preserve S3 data, skip processing if data exists
        - Mode 3 (delete_data=True): Recreate connections + delete S3 data, always reprocess

        Args:
            config: Upload configuration
            delete_data: Whether to delete S3 data during recreation (Mode 3)

        Returns:
            WorkflowResult with recreation and upload outcomes
        """
        mode = "Mode 3" if delete_data else "Mode 2"
        print(f"🔄 {mode}: Starting connection recreation and upload for dataset: {config.dataset_name}")

        return self.workflow_methods.execute_recreate_workflow(config, delete_data=delete_data)
    
    def show_recreate_plan(self, config: UploadConfig) -> WorkflowResult:
        """
        Show what would be deleted/recreated in dry-run mode.
        
        Args:
            config: Upload configuration
            
        Returns:
            WorkflowResult with recreation plan details
        """
        print(f"🔍 Recreate Connections Analysis for dataset: {config.dataset_name}")
        print("=" * 70)
        
        # Generate recreation plan for all organizations
        plan_results = {}
        total_connections = 0
        total_folders = 0
        
        for org in config.organizations:
            org_plan = self.connection_orchestrator.recreate_organization_connections(
                org.name, org.providers, self._build_s3_config_dict(config, org.name), dry_run=True,
                connection_suffix=config.connection_suffix
            )
            
            plan_results[org.name] = org_plan
            total_connections += len(org_plan.get("deleted_connections", []))
            total_folders += len(org_plan.get("deleted_folders", []))
        
        # Display plan summary
        self._display_recreation_plan_summary(plan_results, total_connections, total_folders)
        
        return WorkflowResult(
            status="success",
            dataset=config.dataset_name,
            organizations_processed=len(config.organizations),
            organizations_successful=len(config.organizations),
            results=plan_results,
            mode="recreate_connections_dry_run"
        )
    
    def _execute_append_workflow(self, config: UploadConfig, dry_run: bool = False) -> WorkflowResult:
        """
        Execute integrated append workflow with provider/month coordination.
        
        Uses the new IntegratedAppendOrchestrator for coordinated copy and upload
        phases with proper file sequence management and shared target drops.
        Eliminates file overwriting issues from legacy implementation.
        
        Args:
            config: Upload configuration with append_mode=True
            dry_run: Whether to perform dry run validation only
            
        Returns:
            WorkflowResult with integrated append workflow outcomes
        """
        from ..append.integrated_append_orchestrator import IntegratedAppendOrchestrator
        from ..append.integrated_execution_plan import IntegratedExecutionPlanService, SimpleDropIdGenerator
        from ..append.manifest_reader import ManifestReader
        from ..append.s3_file_copier import S3FileCopier
        from ..append.manifest_manager import ManifestManager
        from src.services.environment_service import EnvironmentService
        
        # Initialize append services with dependency injection
        env_service = EnvironmentService()
        s3_config = env_service.get_s3_config()
        
        import boto3
        s3_client = boto3.client('s3', region_name=s3_config['region'])
        
        # Create integrated append services with dependency injection
        manifest_reader = ManifestReader(
            s3_client=s3_client,
            bucket=s3_config['bucket'],
            root_folder="piedpiper-custom-billing"
        )
        
        s3_file_copier = S3FileCopier(
            s3_client=s3_client,
            bucket=s3_config['bucket'],
            max_workers=5
        )
        
        # Create execution plan service for coordination
        drop_id_generator = SimpleDropIdGenerator()
        execution_plan_service = IntegratedExecutionPlanService(
            manifest_reader=manifest_reader,
            drop_id_generator=drop_id_generator
        )
        
        # Create manifest manager for coordinated updates
        manifest_manager = ManifestManager(
            s3_client=s3_client,
            bucket=s3_config['bucket'],
            root_folder="piedpiper-custom-billing"
        )
        
        # Create S3 formatter for compatibility
        from ..s3.formatter import S3Formatter
        s3_formatter = S3Formatter()
        
        # Create integrated append orchestrator
        integrated_orchestrator = IntegratedAppendOrchestrator(
            manifest_reader=manifest_reader,
            s3_file_copier=s3_file_copier,
            execution_plan_service=execution_plan_service,
            upload_workflow=self.workflow_methods,
            manifest_manager=manifest_manager,
            s3_formatter=s3_formatter
        )
        
        # Execute integrated append workflow
        org_results = integrated_orchestrator.execute_integrated_append_workflow(config, dry_run)
        
        # Convert organization results to WorkflowResult format
        total_orgs = len(org_results)
        successful_orgs = len([r for r in org_results.values() if r.is_successful()])
        
        if successful_orgs == total_orgs:
            status = "success"
        elif successful_orgs > 0:
            status = "partial"
        else:
            status = "failed"
        
        from ..models import WorkflowResult
        return WorkflowResult(
            status=status,
            dataset=config.dataset_name or "integrated-append",
            organizations_processed=total_orgs,
            organizations_successful=successful_orgs,
            results=org_results,
            mode="integrated_append"
        )
    
    def _build_s3_config_dict(self, config: UploadConfig, org_name: str) -> Dict[str, str]:
        """
        Build S3 configuration dictionary.
        
        Args:
            config: Upload configuration
            org_name: Organization name
            
        Returns:
            S3 configuration dictionary
        """
        return {
            "bucket_name": config.s3_bucket,
            "root_folder": "piedpiper-custom-billing",  # Generated uploads use this folder
            "org_folder": org_name
        }
    
    def _display_recreation_plan_summary(
        self,
        plan_results: Dict[str, Any],
        total_connections: int,
        total_folders: int
    ) -> None:
        """
        Display recreation plan summary.
        
        Args:
            plan_results: Recreation plan results per organization
            total_connections: Total connections to be recreated
            total_folders: Total folders to be deleted
        """
        # Display connections to delete
        if total_connections > 0:
            print(f"\n❌ CloudZero Connections to Delete:")
            for org_name, plan in plan_results.items():
                for conn in plan.get("deleted_connections", []):
                    provider = conn.get("provider", "Unknown")
                    conn_id = conn.get("connection_id", conn.get("id", "Unknown"))
                    print(f"   ✗ {conn_id} ({provider})")
        else:
            print(f"\n✅ No CloudZero connections to delete")
        
        # Display S3 folders to delete  
        if total_folders > 0:
            print(f"\n🗂️  S3 Org Folders to Delete:")
            for org_name, plan in plan_results.items():
                for folder in plan.get("deleted_folders", []):
                    prefix = folder.get("prefix", "Unknown")
                    objects = folder.get("objects", 0)
                    print(f"   ✗ {prefix} ({objects} files)")
        else:
            print(f"\n✅ No S3 folders to delete")
        
        # Display connections to recreate
        if total_connections > 0:
            print(f"\n🔄 Connections to Recreate:")
            for org_name, plan in plan_results.items():
                for conn in plan.get("created_connections", []):
                    provider = conn.get("provider", "Unknown")
                    print(f"   ✅ {org_name}/{provider} → new first ingest performance")
        
        # Display impact summary
        print(f"\n📊 Recreation Impact:")
        print(f"   Connections to recreate: {total_connections}")
        print(f"   Organizations affected: {len(plan_results)}")
        print(f"   Folders to clean: {total_folders}")


class UploadServiceFactory:
    """
    Factory for creating UploadWorkflowCoordinator with proper dependencies.
    
    Handles dependency injection and service configuration to eliminate
    hidden dependencies from the coordinator.
    """
    
    @staticmethod
    def create_coordinator(config: UploadConfig) -> UploadWorkflowCoordinator:
        """
        Create UploadWorkflowCoordinator with all dependencies.

        Args:
            config: Upload configuration

        Returns:
            Fully configured UploadWorkflowCoordinator
        """
        # Sync CloudZero API tokens to Secrets Manager
        # Users just update ~/.czbg/.env, sync happens automatically
        UploadServiceFactory._sync_secrets_if_needed()

        # Import services (avoid circular imports)
        from .upload_validation_service import UploadValidationService
        from .data_processing_service import DataProcessingService
        from .streaming_s3_upload_service import StreamingS3UploadService
        from .connection_orchestrator import ConnectionOrchestrator
        from .provider_mapping_service import ProviderMappingService

        from ..s3.uploader import S3Uploader
        from ..s3.formatter import S3Formatter
        from ..s3.config import S3Config
        from ..s3.stage_discovery import StageDiscoveryService
        from ..models import CBFProcessingConfig

        # Create S3 configuration
        upload_type = "generated" if config.is_generated_upload() else "adhoc"
        s3_config = S3Config.from_environment(upload_type)

        # Create provider mapping service
        provider_mapping_service = ProviderMappingService()

        # Create core S3 services
        s3_uploader = S3Uploader(s3_config, provider_mapping_service)
        s3_formatter = S3Formatter()
        stage_discovery = StageDiscoveryService()
        
        # Create processing configuration
        cbf_config = CBFProcessingConfig(mapping_path=config.cbf_mapping_path)

        # Create specialized services
        validation_service = UploadValidationService(s3_uploader, stage_discovery)
        data_processing_service = DataProcessingService(cbf_config, provider_mapping_service)
        s3_upload_service = StreamingS3UploadService(s3_uploader, s3_formatter, data_processing_service)
        connection_orchestrator = ConnectionOrchestrator()
        
        # Create coordinator with all dependencies
        return UploadWorkflowCoordinator(
            validation_service,
            data_processing_service,
            s3_upload_service,
            connection_orchestrator
        )

    @staticmethod
    def _sync_secrets_if_needed() -> None:
        """
        Sync CloudZero API tokens from ~/.czbg/.env to Secrets Manager.

        Skips sync if running in ECS worker (secrets already injected).
        Silent failures to avoid breaking uploads if secrets sync fails.
        """
        try:
            from .secrets_sync_service import SecretsSyncService

            environment = os.getenv("CZBILLGEN_ENV", "dev")
            region = os.getenv("AWS_REGION", "us-east-1")

            sync_service = SecretsSyncService(
                environment=environment,
                region=region
            )
            sync_service.sync_secrets(skip_if_worker=True)

        except Exception:
            # Silent failure - don't break uploads if secrets sync fails
            # ECS workers have secrets injected at container start
            # Local testing can fall back to environment variables
            pass