"""
full_integration.py - Integración completa de todas las fases
Este módulo conecta todos los nuevos engines con el flujo principal.
"""
import logging
from typing import Dict, Any, List, Optional
from pathlib import Path

# Imports de todos los nuevos módulos
from human_feel import HumanFeelEngine
from audio_soundscape import SoundscapeEngine, FXEngine, TonalAnalyzer
from audio_arrangement import DJArrangementEngine, TransitionEngine
from audio_mastering import MasterChain, LoudnessAnalyzer, QASuite, MasteringPreset
from self_ai import AutoPrompter, CritiqueEngine, AutoFixEngine

logger = logging.getLogger("FullIntegration")


class AbletonMCPFullPipeline:
    """
    Pipeline completo que integra todas las fases:
    1. Auto-prompter (Fase 7)
    2. Palette selection (Fase 2)
    3. Arrangement generation (Fase 5)
    4. Human feel (Fase 3)
    5. Soundscape/FX (Fase 4)
    6. Mastering (Fase 6)
    7. QA validation (Fase 6)
    8. Critique & Auto-fix (Fase 7)
    """

    def __init__(self, seed: int = 42):
        self.seed = seed
        self.human_engine = HumanFeelEngine(seed=seed)
        self.soundscape_engine = SoundscapeEngine()
        self.fx_engine = FXEngine()
        self.tonal_analyzer = TonalAnalyzer()
        self.arrangement_engine = DJArrangementEngine(seed=seed)
        self.transition_engine = TransitionEngine()
        self.master_chain = MasterChain()
        self.loudness_analyzer = LoudnessAnalyzer()
        self.qa_suite = QASuite()
        self.auto_prompter = AutoPrompter()
        self.critique_engine = CritiqueEngine()
        self.auto_fix_engine = AutoFixEngine()

    def generate_from_vibe(self, vibe_text: str, apply_full_pipeline: bool = True) -> Dict[str, Any]:
        """
        Generación completa desde descripción de vibe.

        Args:
            vibe_text: Descripción (ej: "dark warehouse techno")
            apply_full_pipeline: Si aplicar todas las fases

        Returns:
            Dict con configuración completa del track
        """
        logger.info(f"Starting generation from vibe: '{vibe_text}'")

        # Fase 7: Auto-prompter
        params = self.auto_prompter.generate_from_vibe(vibe_text)
        logger.info(f"Detected: genre={params['genre']}, bpm={params['bpm']}, key={params['key']}")

        # Preparar configuración
        config = {
            'vibe_params': params,
            'genre': params['genre'],
            'bpm': params['bpm'],
            'key': params['key'],
            'style': params['style'],
            'structure_type': params['structure'],
            'seed': self.seed,
        }

        if apply_full_pipeline:
            config = self._apply_full_pipeline(config)

        return config

    def _apply_full_pipeline(self, config: Dict[str, Any]) -> Dict[str, Any]:
        """Aplica todas las fases del pipeline."""

        # Fase 5: Generar estructura
        structure = self.arrangement_engine.generate_structure(config.get('structure_type', 'standard'))
        config['structure'] = [
            {'name': s.name, 'kind': s.kind, 'bars': s.bars, 'energy': s.energy}
            for s in structure
        ]
        config['dj_friendly'] = self.arrangement_engine.is_dj_friendly(structure)

        # Fase 5: Transiciones
        transitions = self.transition_engine.generate_all_transitions(structure)
        config['transitions'] = transitions

        # Fase 4: Soundscape gaps
        timeline = [{'start': 0, 'end': s.bars * 4, 'kind': s.kind} for s in structure]
        gaps = self.soundscape_engine.detect_ambience_gaps(timeline)
        atmos_events = self.soundscape_engine.fill_with_atmos(gaps, config['genre'], config['key'])
        config['atmos_events'] = atmos_events

        # Fase 4: FX automáticos
        fx_events = []
        for section in structure:
            if section.kind == 'drop':
                riser = self.fx_engine.auto_riser_before_drop(section.bars * 4, 8)
                snare_roll = self.fx_engine.auto_snare_roll(section.bars * 4, 4)
                fx_events.extend([riser, snare_roll])
        config['fx_events'] = fx_events

        # Fase 6: Master chain
        preset = MasteringPreset.get_preset('club' if 'techno' in config['genre'] else 'streaming')
        self.master_chain.set_limiter_ceiling(preset['ceiling'])
        config['master_chain'] = self.master_chain.get_ableton_device_chain()

        # Fase 3: Configurar human feel
        config['human_feel'] = {
            'enabled': True,
            'timing_variation_ms': 5.0,
            'velocity_variance': 0.05,
            'note_skip_prob': 0.02,
            'groove_style': 'shuffle',
            'section_dynamics': True,
        }

        return config

    def critique_and_fix(self, song_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Fase 7: Critique loop y auto-fix.

        Args:
            song_data: Datos de la canción generada

        Returns:
            Resultado con scores y fixes aplicados
        """
        # Critique
        critique = self.critique_engine.critique_song(song_data)

        # Auto-fix si hay weaknesses
        if critique['weaknesses']:
            fixes = self.auto_fix_engine.auto_fix(critique, song_data)
            return {
                'critique': critique,
                'fixes': fixes,
                'final_score': fixes['after_score']
            }

        return {
            'critique': critique,
            'fixes': None,
            'final_score': critique['overall_score']
        }

    def validate_master(self, audio_data: Any) -> Dict[str, Any]:
        """
        Fase 6: Validación completa del master.

        Args:
            audio_data: Datos de audio a validar

        Returns:
            Reporte QA
        """
        return self.qa_suite.run_full_qa(audio_data, {})


# Instancia global
_full_pipeline: Optional[AbletonMCPFullPipeline] = None


def get_full_pipeline(seed: int = 42) -> AbletonMCPFullPipeline:
    """Obtiene instancia del pipeline completo."""
    global _full_pipeline
    if _full_pipeline is None:
        _full_pipeline = AbletonMCPFullPipeline(seed=seed)
    return _full_pipeline


def generate_complete_track(vibe_text: str, seed: int = 42) -> Dict[str, Any]:
    """
    Función de conveniencia para generar un track completo.

    Args:
        vibe_text: Descripción del vibe deseado
        seed: Seed para reproducibilidad

    Returns:
        Configuración completa lista para AbletonMCP
    """
    pipeline = get_full_pipeline(seed)
    return pipeline.generate_from_vibe(vibe_text, apply_full_pipeline=True)
