"""
Processing Pipeline - Пайплайн обработки видео
"""

from typing import List, Optional, Callable, Dict, Any
from .core import FrameworkComponent, ProcessingContext
import time
import logging

class ProcessingPipeline:
    """Пайплайн обработки видео - последовательность компонентов"""

    def __init__(self, steps: List[FrameworkComponent] = None, name: str = "default"):
        self.steps = steps or []
        self.name = name
        self.logger = logging.getLogger(f"framework.pipeline.{name}")
        self.middleware: List[Callable] = []

    def add_step(self, component: FrameworkComponent) -> 'ProcessingPipeline':
        """Добавление шага в пайплайн"""
        # Инициализируем компонент перед добавлением
        if not component.initialize():
            raise ValueError(f"Failed to initialize component: {component.name}")

        self.steps.append(component)
        self.logger.info(f"Added step: {component.name}")
        return self

    def add_middleware(self, middleware: Callable) -> 'ProcessingPipeline':
        """Добавление middleware для обработки между шагами"""
        self.middleware.append(middleware)
        return self

    def execute(self, context: ProcessingContext) -> ProcessingContext:
        """Выполнение пайплайна"""
        self.logger.info(f"Starting pipeline execution: {self.name}")
        start_time = time.time()

        try:
            for i, step in enumerate(self.steps):
                step_start = time.time()
                self.logger.info(f"Executing step {i+1}/{len(self.steps)}: {step.name}")

                # Выполнение middleware перед шагом
                for middleware in self.middleware:
                    context = middleware(context, step, "before")

                # Выполнение шага
                context = step.process(context)

                # Выполнение middleware после шага
                for middleware in self.middleware:
                    context = middleware(context, step, "after")

                step_time = time.time() - step_start
                self.logger.info(f"Step {step.name} completed in {step_time:.2f}s")

                # Обновление прогресса
                if context.progress_callback:
                    progress = (i + 1) / len(self.steps) * 100
                    context.progress_callback(f"Completed {step.name}", progress)

            total_time = time.time() - start_time
            self.logger.info(f"Pipeline {self.name} completed in {total_time:.2f}s")

        except Exception as e:
            self.logger.error(f"Pipeline {self.name} failed: {e}")
            if context.progress_callback:
                context.progress_callback(f"Error: {e}", 0)
            raise

        return context

    def validate(self) -> bool:
        """Валидация пайплайна"""
        if not self.steps:
            self.logger.warning("Pipeline has no steps")
            return False

        for step in self.steps:
            if not step.validate_config():
                self.logger.error(f"Step {step.name} validation failed")
                return False

        return True

    def get_step_names(self) -> List[str]:
        """Получение имен всех шагов"""
        return [step.name for step in self.steps]

class PipelineBuilder:
    """Строитель пайплайнов"""

    def __init__(self, name: str = "custom"):
        self.pipeline = ProcessingPipeline(name=name)

    def add_video_extraction(self, **kwargs) -> 'PipelineBuilder':
        """Добавление шага извлечения аудио из видео"""
        from .components.video import VideoExtractionComponent
        component = VideoExtractionComponent("video_extraction", kwargs)
        self.pipeline.add_step(component)
        return self

    def add_speech_recognition(self, engine: str = "auto", **kwargs) -> 'PipelineBuilder':
        """Добавление шага распознавания речи"""
        from .components.speech import SpeechRecognitionComponent
        config = {"engine": engine, **kwargs}
        component = SpeechRecognitionComponent("speech_recognition", config)
        self.pipeline.add_step(component)
        return self

    def add_translation(self, service: str = "deepl", **kwargs) -> 'PipelineBuilder':
        """Добавление шага перевода"""
        from .components.translation import TranslationComponent
        config = {"service": service, **kwargs}
        component = TranslationComponent("translation", config)
        self.pipeline.add_step(component)
        return self

    def add_speech_synthesis(self, engine: str = "auto", **kwargs) -> 'PipelineBuilder':
        """Добавление шага синтеза речи"""
        from .components.tts import SpeechSynthesisComponent
        config = {"engine": engine, **kwargs}
        component = SpeechSynthesisComponent("speech_synthesis", config)
        self.pipeline.add_step(component)
        return self

    def add_video_assembly(self, **kwargs) -> 'PipelineBuilder':
        """Добавление шага сборки финального видео"""
        from .components.video import VideoAssemblyComponent
        component = VideoAssemblyComponent("video_assembly", kwargs)
        self.pipeline.add_step(component)
        return self

    def add_original_video_translator(self, **kwargs) -> 'PipelineBuilder':
        """Добавление оригинального video_translator.py"""
        from .components.original_wrapper import OriginalVideoTranslatorComponent
        component = OriginalVideoTranslatorComponent("original_video_translator", kwargs)
        self.pipeline.add_step(component)
        return self

    def add_custom_step(self, component: FrameworkComponent) -> 'PipelineBuilder':
        """Добавление пользовательского шага"""
        self.pipeline.add_step(component)
        return self

    def add_logging_middleware(self) -> 'PipelineBuilder':
        """Добавление middleware для логирования"""
        def logging_middleware(context, step, phase):
            if phase == "before":
                step.logger.info(f"Starting {step.name}")
            elif phase == "after":
                step.logger.info(f"Finished {step.name}")
            return context

        self.pipeline.add_middleware(logging_middleware)
        return self

    def add_timing_middleware(self) -> 'PipelineBuilder':
        """Добавление middleware для измерения времени"""
        timings = {}

        def timing_middleware(context, step, phase):
            if phase == "before":
                timings[step.name] = time.time()
            elif phase == "after":
                duration = time.time() - timings.get(step.name, 0)
                context.metadata.setdefault("timings", {})[step.name] = duration
            return context

        self.pipeline.add_middleware(timing_middleware)
        return self

    def build(self) -> ProcessingPipeline:
        """Создание пайплайна"""
        if not self.pipeline.validate():
            raise ValueError("Pipeline validation failed")
        return self.pipeline

# Предустановленные пайплайны
class StandardPipelines:
    """Стандартные пайплайны обработки"""

    @staticmethod
    def full_translation_pipeline(
        speech_engine: str = "auto",
        translation_service: str = "deepl",
        tts_engine: str = "auto"
    ) -> ProcessingPipeline:
        """Полный пайплайн перевода видео"""
        return (PipelineBuilder("full_translation")
                .add_video_extraction()
                .add_speech_recognition(engine=speech_engine)
                .add_translation(service=translation_service)
                .add_speech_synthesis(engine=tts_engine)
                .add_video_assembly()
                .add_logging_middleware()
                .add_timing_middleware()
                .build())

    @staticmethod
    def transcription_only_pipeline(speech_engine: str = "auto") -> ProcessingPipeline:
        """Пайплайн только для транскрипции"""
        return (PipelineBuilder("transcription_only")
                .add_video_extraction()
                .add_speech_recognition(engine=speech_engine)
                .add_logging_middleware()
                .build())

    @staticmethod
    def translation_only_pipeline(translation_service: str = "deepl") -> ProcessingPipeline:
        """Пайплайн только для перевода текста"""
        return (PipelineBuilder("translation_only")
                .add_translation(service=translation_service)
                .add_logging_middleware()
                .build())

    @staticmethod
    def original_system_pipeline(**kwargs) -> ProcessingPipeline:
        """Пайплайн использующий оригинальную систему video_translator.py"""
        return (PipelineBuilder("original_system")
                .add_original_video_translator(**kwargs)
                .add_logging_middleware()
                .build())