"""
Framework Configuration - Конфигурация фреймворка
"""

from dataclasses import dataclass, field, asdict
from typing import Dict, Any, Optional, List
from pathlib import Path
import json
import yaml

@dataclass
class SpeechRecognitionConfig:
    """Конфигурация распознавания речи"""
    default_engine: str = "auto"
    whisper_model: str = "base"
    google_credentials: Optional[str] = None
    sphinx_config: Dict[str, Any] = field(default_factory=dict)
    confidence_threshold: float = 0.8
    language_detection: bool = True

@dataclass
class TranslationConfig:
    """Конфигурация перевода"""
    default_service: str = "deepl"
    deepl_api_key: Optional[str] = None
    google_api_key: Optional[str] = None
    chunk_size: int = 1000
    preserve_formatting: bool = True
    fallback_services: List[str] = field(default_factory=lambda: ["google", "libre"])

@dataclass
class SpeechSynthesisConfig:
    """Конфигурация синтеза речи"""
    default_engine: str = "auto"
    voice_selection: str = "auto"  # auto, male, female, specific_voice_id
    speed: float = 1.0
    pitch: float = 1.0
    volume: float = 1.0
    quality: str = "medium"  # low, medium, high
    google_credentials: Optional[str] = None
    elevenlabs_api_key: Optional[str] = None

@dataclass
class VideoProcessingConfig:
    """Конфигурация обработки видео"""
    output_format: str = "mp4"
    video_codec: str = "libx264"
    audio_codec: str = "aac"
    video_quality: str = "medium"  # low, medium, high
    preserve_original_video: bool = True
    subtitle_generation: bool = True
    subtitle_format: str = "srt"
    temp_dir: Optional[str] = None

@dataclass
class PerformanceConfig:
    """Конфигурация производительности"""
    max_workers: int = 4
    chunk_processing: bool = True
    gpu_acceleration: bool = True
    memory_limit_gb: Optional[float] = None
    parallel_processing: bool = True
    cache_enabled: bool = True
    cache_size_mb: int = 1024

@dataclass
class LoggingConfig:
    """Конфигурация логирования"""
    level: str = "INFO"
    format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
    file_path: Optional[str] = None
    max_file_size_mb: int = 10
    backup_count: int = 5
    console_output: bool = True

@dataclass
class FrameworkConfig:
    """Основная конфигурация фреймворка"""

    # Компоненты конфигурации
    speech_recognition: SpeechRecognitionConfig = field(default_factory=SpeechRecognitionConfig)
    translation: TranslationConfig = field(default_factory=TranslationConfig)
    speech_synthesis: SpeechSynthesisConfig = field(default_factory=SpeechSynthesisConfig)
    video_processing: VideoProcessingConfig = field(default_factory=VideoProcessingConfig)
    performance: PerformanceConfig = field(default_factory=PerformanceConfig)
    logging: LoggingConfig = field(default_factory=LoggingConfig)

    # Общие настройки
    project_name: str = "video-translator-framework"
    version: str = "1.0.0"
    debug_mode: bool = False

    # Пути
    working_directory: Optional[str] = None
    plugins_directory: Optional[str] = None
    models_directory: Optional[str] = None

    def to_dict(self) -> Dict[str, Any]:
        """Преобразование в словарь"""
        return asdict(self)

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'FrameworkConfig':
        """Создание из словаря"""
        # Создаем подконфигурации
        speech_recognition = SpeechRecognitionConfig(**data.get('speech_recognition', {}))
        translation = TranslationConfig(**data.get('translation', {}))
        speech_synthesis = SpeechSynthesisConfig(**data.get('speech_synthesis', {}))
        video_processing = VideoProcessingConfig(**data.get('video_processing', {}))
        performance = PerformanceConfig(**data.get('performance', {}))
        logging = LoggingConfig(**data.get('logging', {}))

        # Убираем подконфигурации из основного словаря
        main_data = {k: v for k, v in data.items() if k not in [
            'speech_recognition', 'translation', 'speech_synthesis',
            'video_processing', 'performance', 'logging'
        ]}

        return cls(
            speech_recognition=speech_recognition,
            translation=translation,
            speech_synthesis=speech_synthesis,
            video_processing=video_processing,
            performance=performance,
            logging=logging,
            **main_data
        )

    def save_to_file(self, file_path: str | Path):
        """Сохранение конфигурации в файл"""
        file_path = Path(file_path)

        if file_path.suffix.lower() == '.json':
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(self.to_dict(), f, indent=2, ensure_ascii=False)
        elif file_path.suffix.lower() in ['.yml', '.yaml']:
            with open(file_path, 'w', encoding='utf-8') as f:
                yaml.dump(self.to_dict(), f, default_flow_style=False, allow_unicode=True)
        else:
            raise ValueError(f"Unsupported file format: {file_path.suffix}")

    @classmethod
    def load_from_file(cls, file_path: str | Path) -> 'FrameworkConfig':
        """Загрузка конфигурации из файла"""
        file_path = Path(file_path)

        if not file_path.exists():
            raise FileNotFoundError(f"Config file not found: {file_path}")

        if file_path.suffix.lower() == '.json':
            with open(file_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
        elif file_path.suffix.lower() in ['.yml', '.yaml']:
            with open(file_path, 'r', encoding='utf-8') as f:
                data = yaml.safe_load(f)
        else:
            raise ValueError(f"Unsupported file format: {file_path.suffix}")

        return cls.from_dict(data)

    def merge_with(self, other: 'FrameworkConfig') -> 'FrameworkConfig':
        """Слияние с другой конфигурацией"""
        self_dict = self.to_dict()
        other_dict = other.to_dict()

        # Рекурсивное слияние словарей
        def merge_dicts(dict1, dict2):
            result = dict1.copy()
            for key, value in dict2.items():
                if key in result and isinstance(result[key], dict) and isinstance(value, dict):
                    result[key] = merge_dicts(result[key], value)
                else:
                    result[key] = value
            return result

        merged_dict = merge_dicts(self_dict, other_dict)
        return FrameworkConfig.from_dict(merged_dict)

    def validate(self) -> List[str]:
        """Валидация конфигурации"""
        errors = []

        # Проверка API ключей
        if self.translation.default_service == "deepl" and not self.translation.deepl_api_key:
            errors.append("DeepL API key is required when using DeepL as default translation service")

        if self.speech_synthesis.default_engine == "google" and not self.speech_synthesis.google_credentials:
            errors.append("Google credentials are required when using Google TTS")

        # Проверка путей
        if self.working_directory and not Path(self.working_directory).exists():
            errors.append(f"Working directory does not exist: {self.working_directory}")

        # Проверка производительности
        if self.performance.max_workers <= 0:
            errors.append("max_workers must be greater than 0")

        if self.performance.memory_limit_gb and self.performance.memory_limit_gb <= 0:
            errors.append("memory_limit_gb must be greater than 0")

        return errors

    def is_valid(self) -> bool:
        """Проверка валидности конфигурации"""
        return len(self.validate()) == 0

class ConfigManager:
    """Менеджер конфигураций"""

    def __init__(self, config_dir: str | Path = None):
        self.config_dir = Path(config_dir) if config_dir else Path.cwd() / "configs"
        self.config_dir.mkdir(exist_ok=True)

    def create_default_config(self) -> FrameworkConfig:
        """Создание конфигурации по умолчанию"""
        return FrameworkConfig()

    def save_preset(self, config: FrameworkConfig, name: str):
        """Сохранение пресета конфигурации"""
        preset_path = self.config_dir / f"{name}.yaml"
        config.save_to_file(preset_path)

    def load_preset(self, name: str) -> FrameworkConfig:
        """Загрузка пресета конфигурации"""
        preset_path = self.config_dir / f"{name}.yaml"
        return FrameworkConfig.load_from_file(preset_path)

    def list_presets(self) -> List[str]:
        """Список доступных пресетов"""
        return [f.stem for f in self.config_dir.glob("*.yaml")]

    def create_preset_configs(self):
        """Создание стандартных пресетов"""

        # Быстрая конфигурация
        fast_config = FrameworkConfig()
        fast_config.speech_recognition.whisper_model = "tiny"
        fast_config.speech_synthesis.quality = "low"
        fast_config.video_processing.video_quality = "low"
        fast_config.performance.max_workers = 2
        self.save_preset(fast_config, "fast")

        # Качественная конфигурация
        quality_config = FrameworkConfig()
        quality_config.speech_recognition.whisper_model = "large"
        quality_config.speech_synthesis.quality = "high"
        quality_config.video_processing.video_quality = "high"
        quality_config.performance.max_workers = 8
        self.save_preset(quality_config, "quality")

        # Сбалансированная конфигурация
        balanced_config = FrameworkConfig()
        balanced_config.speech_recognition.whisper_model = "base"
        balanced_config.speech_synthesis.quality = "medium"
        balanced_config.video_processing.video_quality = "medium"
        balanced_config.performance.max_workers = 4
        self.save_preset(balanced_config, "balanced")

        # Production конфигурация
        production_config = FrameworkConfig()
        production_config.debug_mode = False
        production_config.logging.level = "WARNING"
        production_config.performance.cache_enabled = True
        production_config.performance.gpu_acceleration = True
        self.save_preset(production_config, "production")