"""
MasterOrchestratorSprint55 - Sprint 5.5 Production Pipeline

MASTER orchestrator that coordinates the entire Sprint 5.5 pipeline using micro-tools.
Each phase uses micro-tools with 10s timeout max to avoid MCP timeouts.

Pipeline Phases:
- PHASE 1: Setup (30s) - Create 22 tracks, configure returns
- PHASE 2: Selection (3 min) - Select 96 samples for 8 roles across 8 sections
- PHASE 3: Construction (8 min) - Build 8 sections with automation
- PHASE 4: Mixing (2 min) - Configure buses, sidechain, master chain
- PHASE 5: Export (1 min) - Export WAV and validate

Author: Sprint 5.5 Architecture
"""

import time
import logging
from typing import Dict, List, Optional, Any
from dataclasses import dataclass, field
from datetime import datetime

# Configure logging
logger = logging.getLogger(__name__)


@dataclass
class PhaseResult:
    """Result from a single pipeline phase"""
    phase_name: str
    success: bool
    duration_seconds: float
    message: str
    details: Dict[str, Any] = field(default_factory=dict)
    errors: List[str] = field(default_factory=list)


@dataclass
class ProductionState:
    """Tracks the current state of production"""
    phase: str = "idle"
    current_section: int = 0
    total_sections: int = 8
    samples_selected: int = 0
    samples_validated: int = 0
    tracks_created: int = 0
    sections_built: int = 0
    coherence_scores: List[float] = field(default_factory=list)
    start_time: Optional[float] = None
    errors: List[str] = field(default_factory=list)


class ProgressTracker:
    """Real-time progress tracking with detailed reporting"""
    
    def __init__(self, total_steps: int = 100):
        self.total_steps = total_steps
        self.current_step = 0
        self.step_labels: Dict[int, str] = {}
        self.phase_times: Dict[str, float] = {}
        self._phase_start: Optional[float] = None
        
    def set_phase(self, phase_name: str, steps_in_phase: int):
        """Start a new phase with expected steps"""
        if self._phase_start:
            # Record previous phase time
            prev_phase = [k for k, v in self.phase_times.items() if v == 0]
            if prev_phase:
                self.phase_times[prev_phase[0]] = time.time() - self._phase_start
        
        self._phase_start = time.time()
        self.phase_times[phase_name] = 0
        logger.info(f"[PHASE START] {phase_name} ({steps_in_phase} steps)")
        
    def report(self, step: int, message: str, detail: Optional[Dict] = None):
        """Report progress for a specific step"""
        self.current_step = step
        progress_pct = (step / self.total_steps) * 100
        
        # Build status line
        status = f"[{progress_pct:5.1f}%] {message}"
        if detail:
            details_str = ", ".join([f"{k}={v}" for k, v in detail.items()])
            status += f" | {details_str}"
        
        logger.info(status)
        self.step_labels[step] = message
        
        return {
            "step": step,
            "total": self.total_steps,
            "progress_pct": progress_pct,
            "message": message,
            "detail": detail or {},
            "timestamp": datetime.now().isoformat()
        }
    
    def phase_complete(self, phase_name: str, result: Dict):
        """Mark phase as complete with timing"""
        if self._phase_start:
            duration = time.time() - self._phase_start
            self.phase_times[phase_name] = duration
            logger.info(f"[PHASE COMPLETE] {phase_name}: {duration:.1f}s - {result.get('status', 'OK')}")


class MicroToolWrapper:
    """
    Wrapper for micro-tools with timeout protection.
    Each micro-tool must complete within 10 seconds.
    """
    
    def __init__(self, timeout_seconds: float = 10.0):
        self.timeout = timeout_seconds
        self.call_count = 0
        self.error_count = 0
        
    def call(self, tool_name: str, **kwargs) -> Dict:
        """
        Call a micro-tool with timeout protection.
        
        Args:
            tool_name: Name of the tool to call
            **kwargs: Tool arguments
            
        Returns:
            Dict with result or error
        """
        self.call_count += 1
        start = time.time()
        
        try:
            # Import and call the actual micro-tool
            result = self._dispatch_tool(tool_name, **kwargs)
            elapsed = time.time() - start
            
            if elapsed > self.timeout:
                logger.warning(f"Tool {tool_name} slow: {elapsed:.1f}s > {self.timeout}s timeout")
            
            return {
                "success": True,
                "tool": tool_name,
                "elapsed_seconds": elapsed,
                "result": result
            }
            
        except Exception as e:
            self.error_count += 1
            elapsed = time.time() - start
            logger.error(f"Tool {tool_name} failed after {elapsed:.1f}s: {e}")
            
            return {
                "success": False,
                "tool": tool_name,
                "elapsed_seconds": elapsed,
                "error": str(e),
                "error_type": type(e).__name__
            }
    
    def _dispatch_tool(self, tool_name: str, **kwargs) -> Dict:
        """Dispatch to actual micro-tool implementation"""
        # This will be wired to actual micro-tools
        # For now, return placeholder that real implementation will override
        
        tool_mapping = {
            # Phase 1: Setup tools
            "verify_or_create_tracks": self._tool_verify_tracks,
            "configure_return_track": self._tool_configure_return,
            "set_tempo": self._tool_set_tempo,
            
            # Phase 2: Selection tools
            "smart_select_kit": self._tool_smart_select,
            "validate_coherence": self._tool_validate_coherence,
            "distribute_samples": self._tool_distribute_samples,
            
            # Phase 3: Construction tools
            "build_section_real": self._tool_build_section,
            "apply_section_automation": self._tool_apply_automation,
            "create_fx_hit": self._tool_create_fx,
            
            # Phase 4: Mixing tools
            "configure_bus": self._tool_configure_bus,
            "apply_sidechain": self._tool_apply_sidechain,
            "apply_master_chain": self._tool_apply_master,
            
            # Phase 5: Export tools
            "export_wav": self._tool_export_wav,
            "validate_export": self._tool_validate_export,
        }
        
        tool_func = tool_mapping.get(tool_name)
        if not tool_func:
            raise ValueError(f"Unknown micro-tool: {tool_name}")
        
        return tool_func(**kwargs)
    
    # === Phase 1: Setup Tools ===
    def _tool_verify_tracks(self, track_count: int = 22, **kwargs) -> Dict:
        """Verify or create N tracks.
        
        TODO: Wire to live_bridge.create_midi_track() / create_audio_track()
        for real track creation. Currently returns a stub result.
        """
        logger.warning("[STUB] _tool_verify_tracks called but not connected to live_bridge")
        return {"tracks_verified": track_count, "action": "verify_or_create", "stub": True}
    
    def _tool_configure_return(self, return_type: str = "reverb", **kwargs) -> Dict:
        """Configure a return track with effect.
        
        TODO: Wire to live_bridge.create_return_track() for real return creation.
        Currently returns a stub result.
        """
        logger.warning("[STUB] _tool_configure_return called but not connected to live_bridge")
        return {"return_type": return_type, "configured": True, "stub": True}
    
    def _tool_set_tempo(self, tempo: int = 95, **kwargs) -> Dict:
        """Set project tempo.
        
        TODO: Wire to live_bridge.set_tempo() for real tempo changes.
        Currently returns a stub result.
        """
        logger.warning("[STUB] _tool_set_tempo called but not connected to live_bridge")
        return {"tempo": tempo, "set": True, "stub": True}
    
    # === Phase 2: Selection Tools ===
    def _tool_smart_select(self, role: str, count: int = 12, **kwargs) -> Dict:
        """Smart sample selection for a role.
        
        TODO: Wire to SampleSelector.select_for_genre() for real sample selection.
        Currently returns a stub result.
        """
        logger.warning("[STUB] _tool_smart_select called but not connected to SampleSelector")
        return {"role": role, "samples_selected": count, "method": "smart_coherent", "stub": True}
    
    def _tool_validate_coherence(self, samples: List[str], threshold: float = 0.90, **kwargs) -> Dict:
        """Validate sample coherence.
        
        TODO: Wire to CoherenceScorer for real coherence validation.
        Currently returns a stub result.
        """
        logger.warning("[STUB] _tool_validate_coherence called but not connected to CoherenceScorer")
        return {"samples": len(samples), "coherence": 0.92, "valid": True, "stub": True}
    
    def _tool_distribute_samples(self, samples: List[str], sections: int = 8, **kwargs) -> Dict:
        """Distribute samples across sections."""
        per_section = len(samples) // max(sections, 1)
        return {"total_samples": len(samples), "sections": sections, "per_section": per_section}
    
    # === Phase 3: Construction Tools ===
    def _tool_build_section(self, section_type: str, section_index: int, **kwargs) -> Dict:
        """Build a complete section with audio/MIDI.
        
        TODO: Wire to section_builder_real.build_section_real() for real section building.
        Currently returns a stub result.
        """
        logger.warning("[STUB] _tool_build_section called but not connected to section builder")
        return {"section": section_type, "index": section_index, "built": True, "clips": 6, "stub": True}
    
    def _tool_apply_automation(self, section_index: int, automation_type: str = "full", **kwargs) -> Dict:
        """Apply automation package to section.
        
        TODO: Wire to advanced_automation or live_bridge.add_automation().
        Currently returns a stub result.
        """
        logger.warning("[STUB] _tool_apply_automation called but not connected to automation engine")
        return {"section_index": section_index, "automation": automation_type, "applied": True, "stub": True}
    
    def _tool_create_fx(self, position: float, fx_type: str = "riser", **kwargs) -> Dict:
        """Create FX hit at position.
        
        TODO: Wire to pattern_library.PercussionLibrary.get_fx_hit().
        Currently returns a stub result.
        """
        logger.warning("[STUB] _tool_create_fx called but not connected to pattern library")
        return {"position": position, "fx_type": fx_type, "created": True, "stub": True}
    
    # === Phase 4: Mixing Tools ===
    def _tool_configure_bus(self, bus_type: str = "drums", **kwargs) -> Dict:
        """Configure a bus track.
        
        TODO: Wire to bus_architecture.BusRouter for real bus routing.
        Currently returns a stub result.
        """
        logger.warning("[STUB] _tool_configure_bus called but not connected to bus architecture")
        return {"bus_type": bus_type, "configured": True, "stub": True}
    
    def _tool_apply_sidechain(self, source: str = "kick", targets: List[str] = None, **kwargs) -> Dict:
        """Apply sidechain compression.
        
        TODO: Wire to live_bridge.setup_sidechain() for real sidechain setup.
        Currently returns a stub result.
        """
        logger.warning("[STUB] _tool_apply_sidechain called but not connected to live_bridge")
        return {"source": source, "targets": targets or [], "applied": True, "stub": True}
    
    def _tool_apply_master(self, preset: str = "standard", **kwargs) -> Dict:
        """Apply master processing chain.
        
        TODO: Wire to live_bridge.apply_master_chain() for real master chain.
        Currently returns a stub result.
        """
        logger.warning("[STUB] _tool_apply_master called but not connected to live_bridge")
        return {"preset": preset, "applied": True, "stub": True}
    
    # === Phase 5: Export Tools ===
    def _tool_export_wav(self, output_path: str = "", **kwargs) -> Dict:
        """Export to WAV.
        
        TODO: Wire to export_engine or live_bridge.export_project().
        Currently returns a stub result.
        """
        logger.warning("[STUB] _tool_export_wav called but not connected to export engine")
        return {"output": output_path or "output.wav", "exported": True, "duration_seconds": 240, "stub": True}
    
    def _tool_validate_export(self, file_path: str, **kwargs) -> Dict:
        """Validate exported file.
        
        TODO: Wire to quality_assurance for real validation.
        Currently returns a stub result.
        """
        logger.warning("[STUB] _tool_validate_export called but not connected to QA")
        return {"file": file_path, "valid": True, "size_mb": 42.0, "stub": True}


class MasterOrchestratorSprint55:
    """
    Master orchestrator for Sprint 5.5 radio edit production.
    
    Coordinates 5 phases using micro-tools (10s timeout max each):
    1. Setup (30s) - 22 tracks, returns
    2. Selection (3 min) - 96 samples for 8 roles
    3. Construction (8 min) - 8 sections with automation
    4. Mixing (2 min) - buses, sidechain, master
    5. Export (1 min) - WAV export and validation
    
    Total: ~14.5 minutes for complete 4-minute radio edit
    """
    
    # 8 sections for 4-minute radio edit
    SECTIONS = [
        {"name": "Intro", "type": "intro", "duration_bars": 8, "energy": 0.3},
        {"name": "Build 1", "type": "build", "duration_bars": 8, "energy": 0.6},
        {"name": "Drop 1", "type": "drop", "duration_bars": 16, "energy": 0.9},
        {"name": "Breakdown", "type": "breakdown", "duration_bars": 8, "energy": 0.4},
        {"name": "Build 2", "type": "build", "duration_bars": 8, "energy": 0.7},
        {"name": "Drop 2", "type": "drop", "duration_bars": 16, "energy": 1.0},
        {"name": "Bridge", "type": "bridge", "duration_bars": 8, "energy": 0.5},
        {"name": "Outro", "type": "outro", "duration_bars": 8, "energy": 0.2},
    ]
    
    # 8 roles for comprehensive production
    ROLES = [
        "kick", "snare", "hihat", "perc",
        "bass", "synth_lead", "synth_pad", "fx"
    ]
    
    def __init__(self):
        self.state = ProductionState()
        self.progress = ProgressTracker(total_steps=100)
        self.tools = MicroToolWrapper(timeout_seconds=10.0)
        self.phase_results: List[PhaseResult] = []
        
    def execute_radio_edit_4min(
        self,
        description: str,
        tempo: int = 95,
        key: str = "Am",
        target_coherence: float = 0.90
    ) -> Dict:
        """
        Execute complete radio edit production pipeline.
        
        Args:
            description: Natural language description of desired track
            tempo: BPM (default 95)
            key: Musical key (default Am)
            target_coherence: Minimum coherence score (default 0.90)
            
        Returns:
            Dict with complete production results
        """
        start_time = time.time()
        self.state.start_time = start_time
        
        logger.info("=" * 60)
        logger.info("MASTER ORCHESTRATOR SPRINT 5.5")
        logger.info(f"Target: 4-minute radio edit")
        logger.info(f"Description: {description}")
        logger.info(f"Tempo: {tempo} BPM | Key: {key}")
        logger.info(f"Target Coherence: {target_coherence}")
        logger.info("=" * 60)
        
        try:
            # Execute 5 phases
            phase1 = self._phase1_setup(tempo, key)
            phase2 = self._phase2_selection(target_coherence)
            phase3 = self._phase3_construction()
            phase4 = self._phase4_mixing()
            phase5 = self._phase5_export()
            
            # Compile final result
            total_duration = time.time() - start_time
            
            result = {
                "success": all([p.success for p in [phase1, phase2, phase3, phase4, phase5]]),
                "total_duration_seconds": total_duration,
                "total_duration_formatted": f"{total_duration // 60:.0f}m {total_duration % 60:.0f}s",
                "description": description,
                "tempo": tempo,
                "key": key,
                "target_coherence": target_coherence,
                "phases": {
                    "setup": self._phase_result_to_dict(phase1),
                    "selection": self._phase_result_to_dict(phase2),
                    "construction": self._phase_result_to_dict(phase3),
                    "mixing": self._phase_result_to_dict(phase4),
                    "export": self._phase_result_to_dict(phase5),
                },
                "state": {
                    "samples_selected": self.state.samples_selected,
                    "samples_validated": self.state.samples_validated,
                    "tracks_created": self.state.tracks_created,
                    "sections_built": self.state.sections_built,
                    "avg_coherence": sum(self.state.coherence_scores) / len(self.state.coherence_scores) if self.state.coherence_scores else 0.0,
                },
                "sections": len(self.SECTIONS),
                "roles": len(self.ROLES),
                "tool_calls": self.tools.call_count,
                "tool_errors": self.tools.error_count,
                "errors": self.state.errors,
                "timestamp": datetime.now().isoformat()
            }
            
            logger.info("=" * 60)
            logger.info("PRODUCTION COMPLETE")
            logger.info(f"Duration: {result['total_duration_formatted']}")
            logger.info(f"Success: {result['success']}")
            logger.info(f"Samples: {result['state']['samples_selected']} selected, {result['state']['avg_coherence']:.2f} avg coherence")
            logger.info(f"Tool calls: {result['tool_calls']} total, {result['tool_errors']} errors")
            logger.info("=" * 60)
            
            return result
            
        except Exception as e:
            logger.critical(f"Pipeline failed: {e}")
            return {
                "success": False,
                "error": str(e),
                "error_type": type(e).__name__,
                "state": self._production_state_to_dict(),
                "timestamp": datetime.now().isoformat()
            }
    
    def _phase1_setup(self, tempo: int, key: str) -> PhaseResult:
        """PHASE 1: Setup (30s) - Create tracks, configure returns"""
        phase_start = time.time()
        self.state.phase = "setup"
        self.progress.set_phase("Setup", steps=5)
        
        logger.info("-" * 40)
        logger.info("PHASE 1: SETUP (30s target)")
        logger.info("-" * 40)
        
        errors = []
        
        # Step 1: Set tempo
        self.progress.report(1, "Setting project tempo...")
        result = self.tools.call("set_tempo", tempo=tempo)
        if not result["success"]:
            errors.append(f"Tempo: {result.get('error')}")
        
        # Step 2: Verify/create 22 tracks
        self.progress.report(2, "Creating 22 tracks...")
        result = self.tools.call("verify_or_create_tracks", track_count=22)
        if result["success"]:
            self.state.tracks_created = 22
        else:
            errors.append(f"Tracks: {result.get('error')}")
        
        # Step 3: Configure Reverb return
        self.progress.report(3, "Configuring Reverb return...")
        result = self.tools.call("configure_return_track", return_type="reverb")
        if not result["success"]:
            errors.append(f"Reverb: {result.get('error')}")
        
        # Step 4: Configure Delay return
        self.progress.report(4, "Configuring Delay return...")
        result = self.tools.call("configure_return_track", return_type="delay")
        if not result["success"]:
            errors.append(f"Delay: {result.get('error')}")
        
        # Step 5: Verify configuration
        self.progress.report(5, "Verifying setup...")
        
        duration = time.time() - phase_start
        success = len(errors) == 0
        
        self.progress.phase_complete("Setup", {
            "status": "OK" if success else "PARTIAL",
            "tracks": self.state.tracks_created,
            "errors": len(errors)
        })
        
        return PhaseResult(
            phase_name="Setup",
            success=success,
            duration_seconds=duration,
            message=f"Created {self.state.tracks_created} tracks, configured returns" if success else "Partial setup with errors",
            details={"tracks": self.state.tracks_created, "returns": ["reverb", "delay"]},
            errors=errors
        )
    
    def _phase2_selection(self, target_coherence: float) -> PhaseResult:
        """PHASE 2: Selection (3 min) - Select 96 samples for 8 roles"""
        phase_start = time.time()
        self.state.phase = "selection"
        self.progress.set_phase("Selection", steps=len(self.ROLES) + 1)
        
        logger.info("-" * 40)
        logger.info("PHASE 2: SELECTION (3 min target)")
        logger.info("-" * 40)
        
        errors = []
        all_samples: Dict[str, List[str]] = {}
        coherence_scores = []
        
        # For each of 8 roles
        for i, role in enumerate(self.ROLES):
            step = i + 1
            self.progress.report(step, f"Selecting samples for {role}...")
            
            # Call smart selector (20s timeout)
            result = self.tools.call("smart_select_kit", role=role, count=12)
            
            if result["success"]:
                samples = result["result"].get("samples_selected", 0)
                self.state.samples_selected += samples
                
                # Validate coherence
                validate_result = self.tools.call(
                    "validate_coherence",
                    samples=[f"{role}_{j}.wav" for j in range(12)],
                    threshold=target_coherence
                )
                
                if validate_result["success"]:
                    coherence = validate_result["result"].get("coherence", 0.0)
                    coherence_scores.append(coherence)
                    self.state.coherence_scores.append(coherence)
                    self.state.samples_validated += samples
                    
                    # Distribute to 8 sections
                    dist_result = self.tools.call(
                        "distribute_samples",
                        samples=[f"{role}_{j}.wav" for j in range(12)],
                        sections=8
                    )
                    
                    if dist_result["success"]:
                        all_samples[role] = [f"{role}_{j}.wav" for j in range(12)]
                    else:
                        errors.append(f"{role} distribution: {dist_result.get('error')}")
                else:
                    errors.append(f"{role} validation: {validate_result.get('error')}")
            else:
                errors.append(f"{role} selection: {result.get('error')}")
        
        # Final report
        avg_coherence = sum(coherence_scores) / len(coherence_scores) if coherence_scores else 0.0
        self.progress.report(len(self.ROLES) + 1, 
                           f"Selected {self.state.samples_selected} samples, avg coherence: {avg_coherence:.2f}")
        
        duration = time.time() - phase_start
        success = len(errors) == 0 and avg_coherence >= target_coherence
        
        self.progress.phase_complete("Selection", {
            "status": "OK" if success else "PARTIAL",
            "samples": self.state.samples_selected,
            "coherence": avg_coherence
        })
        
        return PhaseResult(
            phase_name="Selection",
            success=success,
            duration_seconds=duration,
            message=f"Selected {self.state.samples_selected} samples, avg coherence: {avg_coherence:.2f}",
            details={
                "total_samples": self.state.samples_selected,
                "avg_coherence": avg_coherence,
                "roles_processed": len(all_samples),
                "samples_per_role": 12,
                "sections": 8
            },
            errors=errors
        )
    
    def _phase3_construction(self) -> PhaseResult:
        """PHASE 3: Construction (8 min) - Build 8 sections with automation"""
        phase_start = time.time()
        self.state.phase = "construction"
        self.progress.set_phase("Construction", steps=len(self.SECTIONS) * 2)
        
        logger.info("-" * 40)
        logger.info("PHASE 3: CONSTRUCTION (8 min target)")
        logger.info("-" * 40)
        
        errors = []
        sections_built = 0
        
        # For each of 8 sections (1 min each = ~15s per micro-tool)
        for i, section in enumerate(self.SECTIONS):
            base_step = i * 2 + 1
            
            # Build section (15s)
            self.progress.report(base_step, 
                               f"Building {section['name']} ({section['type']})...",
                               {"energy": section['energy'], "bars": section['duration_bars']})
            
            result = self.tools.call(
                "build_section_real",
                section_type=section['type'],
                section_index=i,
                duration_bars=section['duration_bars']
            )
            
            if result["success"]:
                sections_built += 1
                self.state.sections_built += 1
                
                # Apply automation package (10s)
                self.progress.report(base_step + 1, 
                                   f"Applying automation to {section['name']}...")
                
                auto_result = self.tools.call(
                    "apply_section_automation",
                    section_index=i,
                    automation_type="full"
                )
                
                if not auto_result["success"]:
                    errors.append(f"{section['name']} automation: {auto_result.get('error')}")
            else:
                errors.append(f"{section['name']} build: {result.get('error')}")
        
        duration = time.time() - phase_start
        success = sections_built == len(self.SECTIONS)
        
        self.progress.phase_complete("Construction", {
            "status": "OK" if success else "PARTIAL",
            "sections": sections_built
        })
        
        return PhaseResult(
            phase_name="Construction",
            success=success,
            duration_seconds=duration,
            message=f"Built {sections_built}/{len(self.SECTIONS)} sections with automation",
            details={
                "sections_built": sections_built,
                "total_sections": len(self.SECTIONS),
                "automation_applied": sections_built
            },
            errors=errors
        )
    
    def _phase4_mixing(self) -> PhaseResult:
        """PHASE 4: Mixing (2 min) - Configure buses, sidechain, master"""
        phase_start = time.time()
        self.state.phase = "mixing"
        self.progress.set_phase("Mixing", steps=5)
        
        logger.info("-" * 40)
        logger.info("PHASE 4: MIXING (2 min target)")
        logger.info("-" * 40)
        
        errors = []
        
        # Step 1: Configure drums bus
        self.progress.report(1, "Configuring Drums bus...")
        result = self.tools.call("configure_bus", bus_type="drums")
        if not result["success"]:
            errors.append(f"Drums bus: {result.get('error')}")
        
        # Step 2: Configure synths bus
        self.progress.report(2, "Configuring Synths bus...")
        result = self.tools.call("configure_bus", bus_type="synths")
        if not result["success"]:
            errors.append(f"Synths bus: {result.get('error')}")
        
        # Step 3: Configure FX bus
        self.progress.report(3, "Configuring FX bus...")
        result = self.tools.call("configure_bus", bus_type="fx")
        if not result["success"]:
            errors.append(f"FX bus: {result.get('error')}")
        
        # Step 4: Apply sidechain
        self.progress.report(4, "Applying sidechain compression...")
        result = self.tools.call(
            "apply_sidechain",
            source="kick",
            targets=["bass", "synth_pad"]
        )
        if not result["success"]:
            errors.append(f"Sidechain: {result.get('error')}")
        
        # Step 5: Apply master chain
        self.progress.report(5, "Applying master chain...")
        result = self.tools.call("apply_master_chain", preset="standard")
        if not result["success"]:
            errors.append(f"Master chain: {result.get('error')}")
        
        duration = time.time() - phase_start
        success = len(errors) == 0
        
        self.progress.phase_complete("Mixing", {
            "status": "OK" if success else "PARTIAL",
            "buses": 3,
            "sidechain": True,
            "master": True
        })
        
        return PhaseResult(
            phase_name="Mixing",
            success=success,
            duration_seconds=duration,
            message="Configured buses, sidechain, and master chain" if success else "Partial mix with errors",
            details={
                "buses_configured": ["drums", "synths", "fx"],
                "sidechain_applied": True,
                "master_chain_applied": True
            },
            errors=errors
        )
    
    def _phase5_export(self) -> PhaseResult:
        """PHASE 5: Export (1 min) - Export WAV and validate"""
        phase_start = time.time()
        self.state.phase = "export"
        self.progress.set_phase("Export", steps=3)
        
        logger.info("-" * 40)
        logger.info("PHASE 5: EXPORT (1 min target)")
        logger.info("-" * 40)
        
        errors = []
        
        # Step 1: Export WAV
        self.progress.report(1, "Exporting WAV...")
        output_path = f"radio_edit_{int(time.time())}.wav"
        result = self.tools.call("export_wav", output_path=output_path)
        
        if not result["success"]:
            errors.append(f"Export: {result.get('error')}")
            duration = time.time() - phase_start
            return PhaseResult(
                phase_name="Export",
                success=False,
                duration_seconds=duration,
                message="Export failed",
                details={},
                errors=errors
            )
        
        # Step 2: Validate export
        self.progress.report(2, "Validating export...")
        validate_result = self.tools.call("validate_export", file_path=output_path)
        
        if not validate_result["success"]:
            errors.append(f"Validation: {validate_result.get('error')}")
        
        # Step 3: Report stats
        self.progress.report(3, "Reporting export stats...")
        stats = {
            "file": output_path,
            "duration_seconds": 240,  # 4 minutes
            "size_mb": validate_result["result"].get("size_mb", 0) if validate_result["success"] else 0,
            "valid": validate_result["result"].get("valid", False) if validate_result["success"] else False
        }
        
        duration = time.time() - phase_start
        success = len(errors) == 0 and stats["valid"]
        
        self.progress.phase_complete("Export", {
            "status": "OK" if success else "PARTIAL",
            "file": output_path,
            "size_mb": stats["size_mb"]
        })
        
        return PhaseResult(
            phase_name="Export",
            success=success,
            duration_seconds=duration,
            message=f"Exported {stats['size_mb']:.1f}MB WAV ({stats['duration_seconds']}s)",
            details=stats,
            errors=errors
        )
    
    def _phase_result_to_dict(self, result: PhaseResult) -> Dict:
        """Convert PhaseResult to dict"""
        return {
            "phase_name": result.phase_name,
            "success": result.success,
            "duration_seconds": result.duration_seconds,
            "duration_formatted": f"{result.duration_seconds // 60:.0f}m {result.duration_seconds % 60:.0f}s",
            "message": result.message,
            "details": result.details,
            "errors": result.errors
        }
    
    def _production_state_to_dict(self) -> Dict:
        """Convert ProductionState to dict"""
        return {
            "phase": self.state.phase,
            "current_section": self.state.current_section,
            "total_sections": self.state.total_sections,
            "samples_selected": self.state.samples_selected,
            "samples_validated": self.state.samples_validated,
            "tracks_created": self.state.tracks_created,
            "sections_built": self.state.sections_built,
            "coherence_scores": self.state.coherence_scores,
            "errors": self.state.errors
        }


# Convenience function for direct usage
def create_radio_edit(
    description: str,
    tempo: int = 95,
    key: str = "Am",
    target_coherence: float = 0.90
) -> Dict:
    """
    Create a complete 4-minute radio edit.
    
    Args:
        description: Natural language description
        tempo: BPM
        key: Musical key
        target_coherence: Minimum coherence score
        
    Returns:
        Complete production result dict
    """
    orchestrator = MasterOrchestratorSprint55()
    return orchestrator.execute_radio_edit_4min(
        description=description,
        tempo=tempo,
        key=key,
        target_coherence=target_coherence
    )


if __name__ == "__main__":
    # Test run
    result = create_radio_edit(
        description="reggaeton perreo intenso",
        tempo=95,
        key="Am",
        target_coherence=0.90
    )
    print(f"\nProduction result: {result['success']}")
    print(f"Duration: {result['total_duration_formatted']}")
