"""
Time-shift parallel execution orchestrator.

Thin coordinator that orchestrates parallel time-shift execution by provider.
Delegates all work to specialized services following Single Responsibility Principle.
"""

import uuid
from typing import List
from .time_shift_config_loader import TimeShiftConfigLoader
from .time_shift_config_splitter import TimeShiftConfigSplitter
from .time_shift_job_submitter import TimeShiftJobSubmitter
from .time_shift_job_monitor import TimeShiftJobMonitor
from .time_shift_result_aggregator import TimeShiftResultAggregator
from .time_shift_console_reporter import TimeShiftConsoleReporter
from ..models.parallel_execution_models import (
    ProviderConfig,
    JobSubmission,
    AggregateResult
)


class TimeShiftParallelExecutor:
    """
    Orchestrates parallel time-shift execution by provider.

    Thin coordinator that delegates all work to specialized services.
    Automatically splits config by provider for parallel processing.
    """

    def __init__(
        self,
        config_loader: TimeShiftConfigLoader,
        config_splitter: TimeShiftConfigSplitter,
        job_submitter: TimeShiftJobSubmitter,
        job_monitor: TimeShiftJobMonitor,
        result_aggregator: TimeShiftResultAggregator,
        console_reporter: TimeShiftConsoleReporter
    ):
        """
        Initialize with all service dependencies.

        Args:
            config_loader: Configuration loader service
            config_splitter: Configuration splitter service
            job_submitter: Job submission service
            job_monitor: Job monitoring service
            result_aggregator: Result aggregation service
            console_reporter: Console reporting service
        """
        self.config_loader = config_loader
        self.config_splitter = config_splitter
        self.job_submitter = job_submitter
        self.job_monitor = job_monitor
        self.result_aggregator = result_aggregator
        self.console_reporter = console_reporter

    def execute(self, config_path: str) -> AggregateResult:
        """
        Execute parallel time-shift by provider.

        Flow:
        1. Generate execution ID
        2. Load config
        3. Split by provider (with execution ID for unique message_group_ids)
        4. Submit all jobs
        5. Monitor until complete
        6. Aggregate results

        Args:
            config_path: Path to time-shift configuration file

        Returns:
            AggregateResult with statistics from all providers
        """
        # Generate unique execution ID for this run (multi-user support)
        execution_id = uuid.uuid4().hex[:8]

        config = self.config_loader.load_config(config_path)

        provider_configs = self.config_splitter.split_by_provider(config, execution_id)
        self._report_split(provider_configs, execution_id)

        job_submissions = self._submit_all_jobs(provider_configs)

        self.console_reporter.report_monitoring_start(len(job_submissions))
        provider_results = self.job_monitor.monitor_until_complete(job_submissions)

        aggregate_result = self.result_aggregator.aggregate(provider_results)
        self.console_reporter.report_completion(aggregate_result)

        return aggregate_result

    def _report_split(
        self,
        provider_configs: List[ProviderConfig],
        execution_id: str
    ) -> None:
        """Report config splitting."""
        providers = [pc.provider for pc in provider_configs]
        self.console_reporter.report_split(providers, execution_id)

    def _submit_all_jobs(
        self,
        provider_configs: List[ProviderConfig]
    ) -> List[JobSubmission]:
        """Submit jobs for all provider configs."""
        self.console_reporter.report_submissions_start(len(provider_configs))

        submissions = []
        for pc in provider_configs:
            job_id = self.job_submitter.submit_job(
                config=pc.config,
                dataset_name=pc.dataset_name
            )

            submission = JobSubmission(
                provider=pc.provider,
                job_id=job_id,
                dataset_name=pc.dataset_name
            )
            submissions.append(submission)

            self.console_reporter.report_submission(
                pc.provider,
                job_id,
                pc.dataset_name
            )

        return submissions
