"""
Speech Recognition Component - Компонент распознавания речи
"""

import sys
from pathlib import Path
from typing import Dict, Any, Optional
from ..core import FrameworkComponent, ProcessingContext

# Импорт существующих модулей
project_root = Path(__file__).parent.parent.parent
src_path = project_root / "src"
sys.path.insert(0, str(src_path))

try:
    from core.speech_recognizer import SpeechRecognizer
    SPEECH_RECOGNIZER_AVAILABLE = True
except ImportError as e:
    print(f"Warning: SpeechRecognizer not available: {e}")
    SPEECH_RECOGNIZER_AVAILABLE = False

class SpeechRecognitionComponent(FrameworkComponent):
    """Компонент распознавания речи"""

    def __init__(self, name: str = "speech_recognition", config: Dict[str, Any] = None):
        super().__init__(name, config)
        self.speech_recognizer = None
        self.engine = self.config.get('engine', 'auto')

    def initialize(self) -> bool:
        """Инициализация компонента"""
        if not super().initialize():
            return False

        if not SPEECH_RECOGNIZER_AVAILABLE:
            self.logger.error("SpeechRecognizer module not available")
            return False

        try:
            self.speech_recognizer = SpeechRecognizer()
            self.logger.info(f"Initialized speech recognition with engine: {self.engine}")
            return True
        except Exception as e:
            self.logger.error(f"Failed to initialize SpeechRecognizer: {e}")
            return False

    def validate_config(self) -> bool:
        """Валидация конфигурации"""
        if not super().validate_config():
            return False

        engine = self.config.get('engine', 'auto')
        valid_engines = ['auto', 'whisper', 'google', 'sphinx']

        if engine not in valid_engines:
            self.logger.error(f"Invalid speech engine: {engine}. Valid options: {valid_engines}")
            return False

        return True

    def process(self, context: ProcessingContext) -> ProcessingContext:
        """Обработка: распознавание речи из аудио"""
        if not self.speech_recognizer:
            raise RuntimeError("SpeechRecognizer not initialized")

        # Получаем аудио файл из контекста
        audio_file = context.audio_file
        if not audio_file or not audio_file.exists():
            raise ValueError("Audio file not found in context or doesn't exist")

        self.logger.info(f"Starting speech recognition for: {audio_file}")

        try:
            # Определяем параметры распознавания
            source_language = context.source_language
            if source_language == "auto":
                source_language = None  # Автоопределение

            # Колбэк для обновления прогресса
            def progress_callback(stage, progress):
                if context.progress_callback:
                    context.progress_callback(f"Speech Recognition: {stage}", progress)

            # Выполняем распознавание с fallback стратегией
            text_result = None

            if self.engine == 'whisper' or self.engine == 'auto':
                try:
                    # Пробуем продвинутый метод Whisper для получения временных меток
                    if context.progress_callback:
                        context.progress_callback("Speech Recognition: Using Whisper Advanced", 30)

                    result = self.speech_recognizer.transcribe_with_whisper_advanced(
                        audio_path=str(audio_file),
                        language=source_language if source_language != 'auto' else 'en',
                        model_size=self.config.get('whisper_model', 'base')
                    )

                    if result and 'text' in result and result['text'].strip():
                        context.transcription = result['text']
                        context.metadata['speech_recognition'] = {
                            'engine_used': 'whisper_advanced',
                            'model': result.get('model', 'base'),
                            'language_detected': result.get('language', source_language),
                            'has_word_timestamps': result.get('word_timestamps', False)
                        }

                        # Сохраняем временные метки если есть
                        if 'segments' in result:
                            context.timestamps = result['segments']
                        elif 'sentences' in result:
                            context.timestamps = result['sentences']

                        self.logger.info("Whisper advanced transcription successful")
                        text_result = result['text']
                    else:
                        self.logger.warning("Whisper advanced failed, falling back to basic transcription")

                except Exception as e:
                    self.logger.warning(f"Whisper advanced failed: {e}, falling back to basic transcription")

            # Fallback к базовому методу если продвинутый не сработал
            if not text_result:
                if context.progress_callback:
                    context.progress_callback("Speech Recognition: Using Basic Method", 50)

                text_result = self.speech_recognizer.transcribe_audio(
                    audio_path=str(audio_file),
                    language=source_language if source_language != 'auto' else None
                )

                if text_result and text_result.strip():
                    context.transcription = text_result
                    context.metadata['speech_recognition'] = {
                        'engine_used': self.engine if self.engine != 'auto' else 'auto_fallback',
                        'language_detected': source_language,
                        'method': 'basic_transcribe_audio'
                    }
                    self.logger.info("Basic transcription successful")
                else:
                    raise RuntimeError("Both advanced and basic speech recognition failed - no text returned")

            self.logger.info(f"Speech recognition completed. Text length: {len(context.transcription)} chars")

        except Exception as e:
            self.logger.error(f"Speech recognition failed: {e}")
            raise

        return context

    def get_available_engines(self) -> Dict[str, bool]:
        """Получение списка доступных движков"""
        if not self.speech_recognizer:
            return {}

        try:
            return self.speech_recognizer.test_recognition_engines()
        except Exception as e:
            self.logger.warning(f"Failed to test engines: {e}")
            return {}

    def get_supported_languages(self, engine: str = None) -> list:
        """Получение поддерживаемых языков для движка"""
        if not self.speech_recognizer:
            return []

        engine = engine or self.engine

        # Базовые поддерживаемые языки
        common_languages = [
            'en', 'ru', 'es', 'fr', 'de', 'it', 'pt', 'zh', 'ja', 'ko'
        ]

        if engine == 'whisper':
            # Whisper поддерживает много языков
            return [
                'af', 'am', 'ar', 'as', 'az', 'ba', 'be', 'bg', 'bn', 'bo', 'br', 'bs', 'ca', 'cs', 'cy',
                'da', 'de', 'el', 'en', 'es', 'et', 'eu', 'fa', 'fi', 'fo', 'fr', 'gl', 'gu', 'ha', 'haw',
                'he', 'hi', 'hr', 'ht', 'hu', 'hy', 'id', 'is', 'it', 'ja', 'jw', 'ka', 'kk', 'km', 'kn',
                'ko', 'la', 'lb', 'ln', 'lo', 'lt', 'lv', 'mg', 'mi', 'mk', 'ml', 'mn', 'mr', 'ms', 'mt',
                'my', 'ne', 'nl', 'nn', 'no', 'oc', 'pa', 'pl', 'ps', 'pt', 'ro', 'ru', 'sa', 'sd', 'si',
                'sk', 'sl', 'sn', 'so', 'sq', 'sr', 'su', 'sv', 'sw', 'ta', 'te', 'tg', 'th', 'tk', 'tl',
                'tr', 'tt', 'uk', 'ur', 'uz', 'vi', 'yi', 'yo', 'zh'
            ]
        elif engine == 'google':
            # Google Speech-to-Text поддерживает много языков
            return common_languages + ['nl', 'pl', 'tr', 'uk', 'ar', 'hi', 'th', 'vi']
        else:
            return common_languages

# Вспомогательные функции для работы с аудио
def extract_audio_info(audio_file: Path) -> Dict[str, Any]:
    """Извлечение информации об аудио файле"""
    try:
        import librosa
        y, sr = librosa.load(str(audio_file), sr=None)
        duration = len(y) / sr

        return {
            'duration': duration,
            'sample_rate': sr,
            'channels': 1 if y.ndim == 1 else y.shape[0],
            'samples': len(y)
        }
    except ImportError:
        # Fallback без librosa
        return {
            'duration': 0.0,
            'sample_rate': 16000,
            'channels': 1,
            'samples': 0
        }
    except Exception as e:
        return {'error': str(e)}