"""
SectionBuilderReal - Builds REAL sections in Ableton Live with actual musical content.

This engine creates actual audio/MIDI content in Arrangement View (not just planning):
- Intro: Ambience → Hi-hats → Build with riser
- Verse: 50% energy with full groove
- Build: Rising energy with risers and fills
- Chorus: 100% energy, all elements
- Outro: Fade out with reduced elements

Author: AbletonMCP_AI Senior Architecture v3.0
"""

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

# Setup logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("SectionBuilderReal")


@dataclass
class SectionBuildReport:
    """Detailed report of section creation."""
    section_type: str
    start_bar: float
    duration_bars: int
    status: str
    clips_created: int = 0
    tracks_affected: List[int] = field(default_factory=list)
    samples_used: List[str] = field(default_factory=list)
    errors: List[str] = field(default_factory=list)
    details: Dict[str, Any] = field(default_factory=dict)


class SectionBuilderReal:
    """
    Builds real musical sections in Ableton Live Arrangement View.
    
    Uses live_bridge for track operations and micro_injector (MultiSampleInjector)
    for placing samples at specific positions.
    
    Each method creates actual content that can be heard immediately.
    """
    
    def __init__(self, live_bridge, micro_injector):
        """
        Initialize SectionBuilderReal with dependencies.
        
        Args:
            live_bridge: AbletonLiveBridge instance for track/clip operations
            micro_injector: MultiSampleInjector instance for sample placement
        """
        self.live_bridge = live_bridge
        self.micro_injector = micro_injector
        self._build_history: List[SectionBuildReport] = []
        
        logger.info("SectionBuilderReal initialized")
    
    def build_intro_real(
        self,
        track_indices: Dict[str, int],
        samples: Dict[str, List[str]],
        duration_bars: int = 8
    ) -> Dict[str, Any]:
        """
        Builds REAL intro section in Ableton Live.
        
        Structure:
        - Bar 0-4: Ambience/drone only (samples 0-1)
        - Bar 4-6: Hi-hats subtle enter (samples 2-3)
        - Bar 6-8: Build with riser (samples 4-5)
        
        Args:
            track_indices: Dict mapping track roles to track indices
                Example: {"ambience": 0, "hihat": 1, "riser": 2}
            samples: Dict mapping section parts to sample lists
                Example: {"ambience": ["drone1.wav", "drone2.wav"],
                         "hihat": ["hat_soft.wav", "hat_closed.wav"],
                         "riser": ["riser1.wav", "riser2.wav"]}
            duration_bars: Total intro duration (default 8 bars)
            
        Returns:
            Dict with detailed build report including:
            - status: "success" or "error"
            - clips_created: Total clips placed
            - phases: What was created in each phase
            - errors: Any errors encountered
        """
        logger.info(f"[INTRO] Building real intro: {duration_bars} bars")
        
        report = SectionBuildReport(
            section_type="intro",
            start_bar=0,
            duration_bars=duration_bars,
            status="in_progress"
        )
        
        clips_total = 0
        phases = []
        
        try:
            # Phase 1: Bar 0-4 - Ambience/Drone only
            phase1_duration = min(4, duration_bars)
            if phase1_duration > 0 and "ambience" in track_indices:
                ambience_track = track_indices["ambience"]
                ambience_samples = samples.get("ambience", [])
                
                if ambience_samples and ambience_track >= 0:
                    # Calculate positions for ambience (spread across phase 1)
                    positions = [float(b) for b in range(0, phase1_duration)]
                    
                    # Use round-robin injection for ambience
                    result = self.micro_injector.inject_round_robin(
                        track_index=ambience_track,
                        samples=ambience_samples[:2],  # Use first 2 samples
                        positions=positions,
                        rotation="2bars"
                    )
                    
                    clips_created = result.get("clips_created", 0)
                    clips_total += clips_created
                    
                    phases.append({
                        "phase": "ambience",
                        "bars": f"0-{phase1_duration}",
                        "track": ambience_track,
                        "clips": clips_created,
                        "status": result.get("status", "unknown")
                    })
                    
                    report.samples_used.extend(ambience_samples[:2])
                    if ambience_track not in report.tracks_affected:
                        report.tracks_affected.append(ambience_track)
                    
                    logger.info(f"[INTRO] Phase 1 (ambience): {clips_created} clips at bars 0-{phase1_duration}")
                else:
                    phases.append({
                        "phase": "ambience",
                        "bars": f"0-{phase1_duration}",
                        "skipped": True,
                        "reason": "Missing track or samples"
                    })
            
            # Phase 2: Bar 4-6 - Hi-hats subtle enter
            phase2_start = 4
            phase2_duration = min(2, duration_bars - phase2_start)
            if phase2_duration > 0 and phase2_start < duration_bars and "hihat" in track_indices:
                hihat_track = track_indices["hihat"]
                hihat_samples = samples.get("hihat", [])
                
                if hihat_samples and hihat_track >= 0:
                    # Calculate positions for hi-hats (every beat for subtle entry)
                    positions = []
                    for bar in range(phase2_start, phase2_start + phase2_duration):
                        for beat in range(0, 4, 2):  # Every 2 beats = half time feel
                            positions.append(float(bar) + beat / 4.0)
                    
                    result = self.micro_injector.inject_pattern(
                        track_index=hihat_track,
                        samples=hihat_samples[:2],  # Use first 2 samples
                        pattern=[0, 1] * (len(positions) // 2 + 1),
                        positions=positions
                    )
                    
                    clips_created = result.get("clips_created", 0)
                    clips_total += clips_created
                    
                    phases.append({
                        "phase": "hihats_subtle",
                        "bars": f"{phase2_start}-{phase2_start + phase2_duration}",
                        "track": hihat_track,
                        "clips": clips_created,
                        "status": result.get("status", "unknown")
                    })
                    
                    report.samples_used.extend(hihat_samples[:2])
                    if hihat_track not in report.tracks_affected:
                        report.tracks_affected.append(hihat_track)
                    
                    logger.info(f"[INTRO] Phase 2 (hi-hats): {clips_created} clips at bars {phase2_start}-{phase2_start + phase2_duration}")
                else:
                    phases.append({
                        "phase": "hihats_subtle",
                        "bars": f"{phase2_start}-{phase2_start + phase2_duration}",
                        "skipped": True,
                        "reason": "Missing track or samples"
                    })
            
            # Phase 3: Bar 6-8 - Build with riser
            phase3_start = 6
            phase3_duration = duration_bars - phase3_start
            if phase3_duration > 0 and "riser" in track_indices:
                riser_track = track_indices["riser"]
                riser_samples = samples.get("riser", [])
                
                if riser_samples and riser_track >= 0:
                    # Place riser at start of phase 3
                    positions = [float(phase3_start)]
                    
                    result = self.micro_injector.inject_layered(
                        track_index=riser_track,
                        samples=riser_samples[:2],  # Use first 2 samples layered
                        positions=positions,
                        layers=2,
                        velocity_split=True
                    )
                    
                    clips_created = result.get("clips_created", 0)
                    clips_total += clips_created
                    
                    phases.append({
                        "phase": "build_riser",
                        "bars": f"{phase3_start}-{duration_bars}",
                        "track": riser_track,
                        "clips": clips_created,
                        "status": result.get("status", "unknown")
                    })
                    
                    report.samples_used.extend(riser_samples[:2])
                    if riser_track not in report.tracks_affected:
                        report.tracks_affected.append(riser_track)
                    
                    logger.info(f"[INTRO] Phase 3 (riser): {clips_created} clips at bar {phase3_start}")
                else:
                    phases.append({
                        "phase": "build_riser",
                        "bars": f"{phase3_start}-{duration_bars}",
                        "skipped": True,
                        "reason": "Missing track or samples"
                    })
            
            # Finalize report
            report.status = "success"
            report.clips_created = clips_total
            report.details = {"phases": phases}
            
            logger.info(f"[INTRO] Complete: {clips_total} clips created across {len(phases)} phases")
            
        except Exception as e:
            error_msg = f"Intro build failed: {str(e)}"
            logger.error(f"[INTRO] {error_msg}")
            report.status = "error"
            report.errors.append(error_msg)
            report.details = {"phases": phases, "error": error_msg}
        
        self._build_history.append(report)
        
        return {
            "status": report.status,
            "section": "intro",
            "duration_bars": duration_bars,
            "clips_created": report.clips_created,
            "tracks_affected": report.tracks_affected,
            "phases": phases,
            "errors": report.errors
        }
    
    def build_verse_real(
        self,
        track_indices: Dict[str, int],
        samples: Dict[str, List[str]],
        start_bar: float,
        duration_bars: int = 24
    ) -> Dict[str, Any]:
        """
        Builds REAL verse section at 50% energy.
        
        Creates a moderate energy verse with:
        - Drums: Full pattern but not too dense
        - Bass: Present but restrained
        - Chords: Sustained pads
        - Melody: Sparse to leave room for vocals
        
        Args:
            track_indices: Dict mapping track roles to indices
                Example: {"drums": 0, "bass": 1, "chords": 2, "melody": 3}
            samples: Dict mapping roles to sample lists
            start_bar: Starting bar position in arrangement
            duration_bars: Length of verse (default 24 bars)
            
        Returns:
            Dict with detailed build report
        """
        logger.info(f"[VERSE] Building real verse: {duration_bars} bars at bar {start_bar}")
        
        report = SectionBuildReport(
            section_type="verse",
            start_bar=start_bar,
            duration_bars=duration_bars,
            status="in_progress"
        )
        
        clips_total = 0
        elements = []
        
        try:
            # Drums - 50% energy (kick + snare pattern, sparse hats)
            if "drums" in track_indices:
                drums_track = track_indices["drums"]
                drum_samples = samples.get("drums", samples.get("kick", []))
                
                if drum_samples and drums_track >= 0:
                    # Create positions for kick on 1 and 3
                    positions = []
                    for bar in range(int(start_bar), int(start_bar + duration_bars)):
                        positions.append(float(bar))  # Beat 1 (kick)
                        positions.append(float(bar) + 2.0)  # Beat 3 (kick)
                    
                    result = self.micro_injector.inject_round_robin(
                        track_index=drums_track,
                        samples=drum_samples,
                        positions=positions,
                        rotation="bar"
                    )
                    
                    clips = result.get("clips_created", 0)
                    clips_total += clips
                    
                    elements.append({
                        "element": "drums_kick",
                        "energy": "50%",
                        "track": drums_track,
                        "clips": clips,
                        "pattern": "kick on 1 & 3"
                    })
                    
                    report.samples_used.extend(drum_samples)
                    if drums_track not in report.tracks_affected:
                        report.tracks_affected.append(drums_track)
                    
                    logger.info(f"[VERSE] Drums: {clips} clips")
            
            # Bass - Present but restrained (simpler pattern)
            if "bass" in track_indices:
                bass_track = track_indices["bass"]
                bass_samples = samples.get("bass", [])
                
                if bass_samples and bass_track >= 0:
                    # Bass every 2 bars for restraint
                    positions = [float(b) for b in range(int(start_bar), int(start_bar + duration_bars), 2)]
                    
                    result = self.micro_injector.inject_round_robin(
                        track_index=bass_track,
                        samples=bass_samples,
                        positions=positions,
                        rotation="2bars"
                    )
                    
                    clips = result.get("clips_created", 0)
                    clips_total += clips
                    
                    elements.append({
                        "element": "bass",
                        "energy": "50%",
                        "track": bass_track,
                        "clips": clips,
                        "pattern": "every 2 bars"
                    })
                    
                    report.samples_used.extend(bass_samples)
                    if bass_track not in report.tracks_affected:
                        report.tracks_affected.append(bass_track)
                    
                    logger.info(f"[VERSE] Bass: {clips} clips")
            
            # Chords - Sustained pads
            if "chords" in track_indices:
                chords_track = track_indices["chords"]
                chord_samples = samples.get("chords", samples.get("pads", []))
                
                if chord_samples and chords_track >= 0:
                    # Chords every 4 bars
                    positions = [float(b) for b in range(int(start_bar), int(start_bar + duration_bars), 4)]
                    
                    result = self.micro_injector.inject_round_robin(
                        track_index=chords_track,
                        samples=chord_samples,
                        positions=positions,
                        rotation="4bars"
                    )
                    
                    clips = result.get("clips_created", 0)
                    clips_total += clips
                    
                    elements.append({
                        "element": "chords",
                        "energy": "50%",
                        "track": chords_track,
                        "clips": clips,
                        "pattern": "every 4 bars"
                    })
                    
                    report.samples_used.extend(chord_samples)
                    if chords_track not in report.tracks_affected:
                        report.tracks_affected.append(chords_track)
                    
                    logger.info(f"[VERSE] Chords: {clips} clips")
            
            # Melody - Sparse for vocal room
            if "melody" in track_indices:
                melody_track = track_indices["melody"]
                melody_samples = samples.get("melody", samples.get("lead", []))
                
                if melody_samples and melody_track >= 0:
                    # Very sparse melody - every 8 bars
                    positions = [float(b) for b in range(int(start_bar), int(start_bar + duration_bars), 8)]
                    
                    result = self.micro_injector.inject_round_robin(
                        track_index=melody_track,
                        samples=melody_samples,
                        positions=positions,
                        rotation="8bars"
                    )
                    
                    clips = result.get("clips_created", 0)
                    clips_total += clips
                    
                    elements.append({
                        "element": "melody",
                        "energy": "25% (sparse)",
                        "track": melody_track,
                        "clips": clips,
                        "pattern": "every 8 bars"
                    })
                    
                    report.samples_used.extend(melody_samples)
                    if melody_track not in report.tracks_affected:
                        report.tracks_affected.append(melody_track)
                    
                    logger.info(f"[VERSE] Melody: {clips} clips")
            
            report.status = "success"
            report.clips_created = clips_total
            report.details = {"elements": elements, "energy": "50%"}
            
            logger.info(f"[VERSE] Complete: {clips_total} clips across {len(elements)} elements")
            
        except Exception as e:
            error_msg = f"Verse build failed: {str(e)}"
            logger.error(f"[VERSE] {error_msg}")
            report.status = "error"
            report.errors.append(error_msg)
            report.details = {"elements": elements, "error": error_msg}
        
        self._build_history.append(report)
        
        return {
            "status": report.status,
            "section": "verse",
            "start_bar": start_bar,
            "duration_bars": duration_bars,
            "clips_created": report.clips_created,
            "tracks_affected": report.tracks_affected,
            "elements": elements,
            "errors": report.errors
        }
    
    def build_build_real(
        self,
        track_indices: Dict[str, int],
        samples: Dict[str, List[str]],
        start_bar: float,
        duration_bars: int = 8
    ) -> Dict[str, Any]:
        """
        Builds REAL build section with rising energy.
        
        Creates tension before the chorus with:
        - Rising intensity drums
        - Riser FX
        - Increasing percussion density
        - Filter sweeps (if automation available)
        
        Args:
            track_indices: Dict mapping track roles to indices
            samples: Dict mapping roles to sample lists
            start_bar: Starting bar position
            duration_bars: Build duration (default 8 bars)
            
        Returns:
            Dict with detailed build report
        """
        logger.info(f"[BUILD] Building real build section: {duration_bars} bars at bar {start_bar}")
        
        report = SectionBuildReport(
            section_type="build",
            start_bar=start_bar,
            duration_bars=duration_bars,
            status="in_progress"
        )
        
        clips_total = 0
        elements = []
        
        try:
            # Phase 1: Bar 1-4 - Increasing drum density
            if "drums" in track_indices:
                drums_track = track_indices["drums"]
                drum_samples = samples.get("drums", [])
                
                if drum_samples and drums_track >= 0:
                    # More frequent as build progresses
                    positions = []
                    for bar in range(int(start_bar), int(start_bar + duration_bars)):
                        density = 2 + (bar - int(start_bar)) // 2  # Increasing density
                        for i in range(density):
                            pos = float(bar) + (i * 4.0 / density)
                            positions.append(pos)
                    
                    result = self.micro_injector.inject_round_robin(
                        track_index=drums_track,
                        samples=drum_samples,
                        positions=positions,
                        rotation="beat"
                    )
                    
                    clips = result.get("clips_created", 0)
                    clips_total += clips
                    
                    elements.append({
                        "element": "drums_increasing",
                        "track": drums_track,
                        "clips": clips,
                        "intensity": "rising"
                    })
                    
                    report.samples_used.extend(drum_samples)
                    if drums_track not in report.tracks_affected:
                        report.tracks_affected.append(drums_track)
                    
                    logger.info(f"[BUILD] Drums: {clips} clips with increasing density")
            
            # Phase 2: Riser FX
            if "riser" in track_indices:
                riser_track = track_indices["riser"]
                riser_samples = samples.get("riser", samples.get("fx", []))
                
                if riser_samples and riser_track >= 0:
                    # Long riser starting at bar 4 of build
                    riser_start = start_bar + (duration_bars // 2)
                    positions = [float(riser_start)]
                    
                    result = self.micro_injector.inject_layered(
                        track_index=riser_track,
                        samples=riser_samples[:2],
                        positions=positions,
                        layers=2,
                        velocity_split=False
                    )
                    
                    clips = result.get("clips_created", 0)
                    clips_total += clips
                    
                    elements.append({
                        "element": "riser",
                        "track": riser_track,
                        "clips": clips,
                        "start_bar": riser_start
                    })
                    
                    report.samples_used.extend(riser_samples[:2])
                    if riser_track not in report.tracks_affected:
                        report.tracks_affected.append(riser_track)
                    
                    logger.info(f"[BUILD] Riser: {clips} clips starting at bar {riser_start}")
            
            # Phase 3: Percussion fills
            if "perc" in track_indices:
                perc_track = track_indices["perc"]
                perc_samples = samples.get("perc", samples.get("percussion", []))
                
                if perc_samples and perc_track >= 0:
                    # Fill at the end of build
                    fill_start = start_bar + duration_bars - 2
                    positions = []
                    for bar in range(int(fill_start), int(start_bar + duration_bars)):
                        for beat in range(4):
                            positions.append(float(bar) + beat / 4.0)
                    
                    result = self.micro_injector.inject_pattern(
                        track_index=perc_track,
                        samples=perc_samples,
                        pattern=list(range(min(len(perc_samples), 4))),
                        positions=positions
                    )
                    
                    clips = result.get("clips_created", 0)
                    clips_total += clips
                    
                    elements.append({
                        "element": "percussion_fill",
                        "track": perc_track,
                        "clips": clips,
                        "timing": "end of build"
                    })
                    
                    report.samples_used.extend(perc_samples)
                    if perc_track not in report.tracks_affected:
                        report.tracks_affected.append(perc_track)
                    
                    logger.info(f"[BUILD] Percussion fill: {clips} clips")
            
            report.status = "success"
            report.clips_created = clips_total
            report.details = {"elements": elements, "intensity": "rising"}
            
            logger.info(f"[BUILD] Complete: {clips_total} clips across {len(elements)} elements")
            
        except Exception as e:
            error_msg = f"Build section failed: {str(e)}"
            logger.error(f"[BUILD] {error_msg}")
            report.status = "error"
            report.errors.append(error_msg)
            report.details = {"elements": elements, "error": error_msg}
        
        self._build_history.append(report)
        
        return {
            "status": report.status,
            "section": "build",
            "start_bar": start_bar,
            "duration_bars": duration_bars,
            "clips_created": report.clips_created,
            "tracks_affected": report.tracks_affected,
            "elements": elements,
            "errors": report.errors
        }
    
    def build_chorus_real(
        self,
        track_indices: Dict[str, int],
        samples: Dict[str, List[str]],
        start_bar: float,
        duration_bars: int = 24
    ) -> Dict[str, Any]:
        """
        Builds REAL chorus section at 100% energy.
        
        Maximum energy with all elements:
        - Full drums (kick, snare, hats)
        - Full bass
        - Chords/pads
        - Lead melody
        - FX impacts
        
        Args:
            track_indices: Dict mapping track roles to indices
            samples: Dict mapping roles to sample lists
            start_bar: Starting bar position
            duration_bars: Chorus duration (default 24 bars)
            
        Returns:
            Dict with detailed build report
        """
        logger.info(f"[CHORUS] Building real chorus: {duration_bars} bars at bar {start_bar}")
        
        report = SectionBuildReport(
            section_type="chorus",
            start_bar=start_bar,
            duration_bars=duration_bars,
            status="in_progress"
        )
        
        clips_total = 0
        elements = []
        
        try:
            # Drums - Full energy
            if "drums" in track_indices:
                drums_track = track_indices["drums"]
                drum_samples = samples.get("drums", [])
                
                if drum_samples and drums_track >= 0:
                    # Every beat for full energy
                    positions = []
                    for bar in range(int(start_bar), int(start_bar + duration_bars)):
                        for beat in range(4):
                            positions.append(float(bar) + beat / 4.0)
                    
                    result = self.micro_injector.inject_round_robin(
                        track_index=drums_track,
                        samples=drum_samples,
                        positions=positions,
                        rotation="beat"
                    )
                    
                    clips = result.get("clips_created", 0)
                    clips_total += clips
                    
                    elements.append({
                        "element": "drums_full",
                        "energy": "100%",
                        "track": drums_track,
                        "clips": clips,
                        "pattern": "every beat"
                    })
                    
                    report.samples_used.extend(drum_samples)
                    if drums_track not in report.tracks_affected:
                        report.tracks_affected.append(drums_track)
                    
                    logger.info(f"[CHORUS] Drums: {clips} clips")
            
            # Bass - Full
            if "bass" in track_indices:
                bass_track = track_indices["bass"]
                bass_samples = samples.get("bass", [])
                
                if bass_samples and bass_track >= 0:
                    # Every bar
                    positions = [float(b) for b in range(int(start_bar), int(start_bar + duration_bars))]
                    
                    result = self.micro_injector.inject_round_robin(
                        track_index=bass_track,
                        samples=bass_samples,
                        positions=positions,
                        rotation="bar"
                    )
                    
                    clips = result.get("clips_created", 0)
                    clips_total += clips
                    
                    elements.append({
                        "element": "bass_full",
                        "energy": "100%",
                        "track": bass_track,
                        "clips": clips
                    })
                    
                    report.samples_used.extend(bass_samples)
                    if bass_track not in report.tracks_affected:
                        report.tracks_affected.append(bass_track)
                    
                    logger.info(f"[CHORUS] Bass: {clips} clips")
            
            # Chords - Full
            if "chords" in track_indices:
                chords_track = track_indices["chords"]
                chord_samples = samples.get("chords", [])
                
                if chord_samples and chords_track >= 0:
                    # Every 2 bars
                    positions = [float(b) for b in range(int(start_bar), int(start_bar + duration_bars), 2)]
                    
                    result = self.micro_injector.inject_round_robin(
                        track_index=chords_track,
                        samples=chord_samples,
                        positions=positions,
                        rotation="2bars"
                    )
                    
                    clips = result.get("clips_created", 0)
                    clips_total += clips
                    
                    elements.append({
                        "element": "chords_full",
                        "energy": "100%",
                        "track": chords_track,
                        "clips": clips
                    })
                    
                    report.samples_used.extend(chord_samples)
                    if chords_track not in report.tracks_affected:
                        report.tracks_affected.append(chords_track)
                    
                    logger.info(f"[CHORUS] Chords: {clips} clips")
            
            # Melody - Full lead
            if "melody" in track_indices:
                melody_track = track_indices["melody"]
                melody_samples = samples.get("melody", samples.get("lead", []))
                
                if melody_samples and melody_track >= 0:
                    # Every 4 bars for lead lines
                    positions = [float(b) for b in range(int(start_bar), int(start_bar + duration_bars), 4)]
                    
                    result = self.micro_injector.inject_round_robin(
                        track_index=melody_track,
                        samples=melody_samples,
                        positions=positions,
                        rotation="4bars"
                    )
                    
                    clips = result.get("clips_created", 0)
                    clips_total += clips
                    
                    elements.append({
                        "element": "melody_lead",
                        "energy": "100%",
                        "track": melody_track,
                        "clips": clips
                    })
                    
                    report.samples_used.extend(melody_samples)
                    if melody_track not in report.tracks_affected:
                        report.tracks_affected.append(melody_track)
                    
                    logger.info(f"[CHORUS] Melody: {clips} clips")
            
            # FX - Impacts at start
            if "fx" in track_indices:
                fx_track = track_indices["fx"]
                fx_samples = samples.get("fx", samples.get("impact", []))
                
                if fx_samples and fx_track >= 0:
                    # Impact at chorus start
                    positions = [float(start_bar)]
                    
                    result = self.micro_injector.inject_layered(
                        track_index=fx_track,
                        samples=fx_samples[:2],
                        positions=positions,
                        layers=min(2, len(fx_samples)),
                        velocity_split=True
                    )
                    
                    clips = result.get("clips_created", 0)
                    clips_total += clips
                    
                    elements.append({
                        "element": "fx_impact",
                        "energy": "100%",
                        "track": fx_track,
                        "clips": clips,
                        "timing": "chorus start"
                    })
                    
                    report.samples_used.extend(fx_samples[:2])
                    if fx_track not in report.tracks_affected:
                        report.tracks_affected.append(fx_track)
                    
                    logger.info(f"[CHORUS] FX impact: {clips} clips")
            
            report.status = "success"
            report.clips_created = clips_total
            report.details = {"elements": elements, "energy": "100%"}
            
            logger.info(f"[CHORUS] Complete: {clips_total} clips across {len(elements)} elements")
            
        except Exception as e:
            error_msg = f"Chorus build failed: {str(e)}"
            logger.error(f"[CHORUS] {error_msg}")
            report.status = "error"
            report.errors.append(error_msg)
            report.details = {"elements": elements, "error": error_msg}
        
        self._build_history.append(report)
        
        return {
            "status": report.status,
            "section": "chorus",
            "start_bar": start_bar,
            "duration_bars": duration_bars,
            "clips_created": report.clips_created,
            "tracks_affected": report.tracks_affected,
            "elements": elements,
            "errors": report.errors
        }
    
    def build_outro_real(
        self,
        track_indices: Dict[str, int],
        samples: Dict[str, List[str]],
        start_bar: float,
        duration_bars: int = 4
    ) -> Dict[str, Any]:
        """
        Builds REAL outro section with fade out.
        
        Creates an ending with:
        - Reduced elements (strip back to basics)
        - Fade out automation (if available)
        - Optional final impact
        
        Args:
            track_indices: Dict mapping track roles to indices
            samples: Dict mapping roles to sample lists
            start_bar: Starting bar position
            duration_bars: Outro duration (default 4 bars)
            
        Returns:
            Dict with detailed build report
        """
        logger.info(f"[OUTRO] Building real outro: {duration_bars} bars at bar {start_bar}")
        
        report = SectionBuildReport(
            section_type="outro",
            start_bar=start_bar,
            duration_bars=duration_bars,
            status="in_progress"
        )
        
        clips_total = 0
        elements = []
        
        try:
            # Keep only kick and maybe a pad for outro
            # Phase 1: Reduced drums (kick only on 1)
            if "drums" in track_indices:
                drums_track = track_indices["drums"]
                drum_samples = samples.get("drums", [])
                
                if drum_samples and drums_track >= 0:
                    # Only beat 1 of each bar
                    positions = [float(b) for b in range(int(start_bar), int(start_bar + duration_bars))]
                    
                    result = self.micro_injector.inject_round_robin(
                        track_index=drums_track,
                        samples=drum_samples[:1],  # Just one sample
                        positions=positions,
                        rotation="bar"
                    )
                    
                    clips = result.get("clips_created", 0)
                    clips_total += clips
                    
                    elements.append({
                        "element": "drums_reduced",
                        "track": drums_track,
                        "clips": clips,
                        "pattern": "kick on 1 only"
                    })
                    
                    report.samples_used.extend(drum_samples[:1])
                    if drums_track not in report.tracks_affected:
                        report.tracks_affected.append(drums_track)
                    
                    logger.info(f"[OUTRO] Reduced drums: {clips} clips")
                    
                    # Apply volume automation for fade out if possible
                    try:
                        if self.live_bridge and hasattr(self.live_bridge, 'add_parameter_automation'):
                            fade_points = [
                                [start_bar * 4, 0.8],  # Start at 80%
                                [(start_bar + duration_bars) * 4, 0.0]  # Fade to 0
                            ]
                            self.live_bridge.add_parameter_automation(
                                track_index=drums_track,
                                parameter_name="volume",
                                points=fade_points
                            )
                            elements.append({
                                "element": "fade_automation",
                                "track": drums_track,
                                "type": "volume_fade"
                            })
                    except Exception as fade_error:
                        logger.warning(f"[OUTRO] Could not apply fade automation: {fade_error}")
            
            # Optional: Final impact at start of outro
            if "fx" in track_indices:
                fx_track = track_indices["fx"]
                fx_samples = samples.get("fx", samples.get("impact", []))
                
                if fx_samples and fx_track >= 0:
                    # Single impact at outro start
                    positions = [float(start_bar)]
                    
                    result = self.micro_injector.inject_round_robin(
                        track_index=fx_track,
                        samples=fx_samples[:1],
                        positions=positions,
                        rotation="bar"
                    )
                    
                    clips = result.get("clips_created", 0)
                    clips_total += clips
                    
                    elements.append({
                        "element": "final_impact",
                        "track": fx_track,
                        "clips": clips
                    })
                    
                    report.samples_used.extend(fx_samples[:1])
                    if fx_track not in report.tracks_affected:
                        report.tracks_affected.append(fx_track)
                    
                    logger.info(f"[OUTRO] Final impact: {clips} clips")
            
            report.status = "success"
            report.clips_created = clips_total
            report.details = {"elements": elements, "fade_out": True}
            
            logger.info(f"[OUTRO] Complete: {clips_total} clips across {len(elements)} elements")
            
        except Exception as e:
            error_msg = f"Outro build failed: {str(e)}"
            logger.error(f"[OUTRO] {error_msg}")
            report.status = "error"
            report.errors.append(error_msg)
            report.details = {"elements": elements, "error": error_msg}
        
        self._build_history.append(report)
        
        return {
            "status": report.status,
            "section": "outro",
            "start_bar": start_bar,
            "duration_bars": duration_bars,
            "clips_created": report.clips_created,
            "tracks_affected": report.tracks_affected,
            "elements": elements,
            "errors": report.errors,
            "fade_out": True
        }
    
    def get_build_history(self) -> List[Dict[str, Any]]:
        """
        Get history of all section builds performed.
        
        Returns:
            List of build reports as dictionaries
        """
        return [
            {
                "section_type": r.section_type,
                "start_bar": r.start_bar,
                "duration_bars": r.duration_bars,
                "status": r.status,
                "clips_created": r.clips_created,
                "tracks_affected": r.tracks_affected,
                "samples_used": r.samples_used,
                "errors": r.errors
            }
            for r in self._build_history
        ]
    
    def clear_history(self) -> None:
        """Clear build history."""
        self._build_history.clear()
        logger.info("SectionBuilderReal history cleared")


# Convenience functions for direct usage
def create_section_builder(live_bridge, micro_injector) -> SectionBuilderReal:
    """Factory function to create a SectionBuilderReal instance."""
    return SectionBuilderReal(live_bridge, micro_injector)
