"""
T230: Set Profile CSV
Genera perfil CSV del set para exportación pre-show
"""

import csv
import json
import os
from datetime import datetime
from typing import Dict, List, Any, Optional
from io import StringIO


class SetProfileGenerator:
    """
    Generador de perfiles CSV del set.
    
    T230: Exporta perfil CSV pre-show con metadatos del set.
    """
    
    CSV_COLUMNS = [
        'track_number',
        'section_type',
        'start_bar',
        'end_bar',
        'duration_bars',
        'bpm',
        'key',
        'energy_level',
        'drum_pattern',
        'bass_type',
        'music_layers',
        'fx_count',
        'transition_in',
        'transition_out',
        'notes'
    ]
    
    def __init__(self):
        self.output_dir = os.path.join(
            os.path.dirname(os.path.dirname(__file__)),
            'cloud', 'exports'
        )
        os.makedirs(self.output_dir, exist_ok=True)
    
    def generate_set_profile(self, session_id: str = None) -> Dict[str, Any]:
        """
        Genera perfil completo del set actual.
        
        Args:
            session_id: ID de sesión (opcional)
            
        Returns:
            Perfil del set con CSV y metadatos
        """
        # Obtener información del set
        set_info = self._get_set_info(session_id)
        
        if not set_info:
            return {'error': 'No set information available'}
        
        # Generar filas CSV
        rows = self._generate_csv_rows(set_info)
        
        # Crear CSV
        csv_content = self._create_csv(rows)
        
        # Guardar archivo
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        filename = f'set_profile_{timestamp}.csv'
        filepath = os.path.join(self.output_dir, filename)
        
        with open(filepath, 'w', newline='', encoding='utf-8') as f:
            f.write(csv_content)
        
        return {
            'success': True,
            'session_id': session_id or 'current',
            'filepath': filepath,
            'filename': filename,
            'sections_count': len(rows),
            'csv_preview': csv_content[:500] + '...' if len(csv_content) > 500 else csv_content,
            'metadata': {
                'total_bars': sum(r.get('duration_bars', 0) for r in rows),
                'bpm_range': self._calculate_bpm_range(rows),
                'energy_arc': self._calculate_energy_arc(rows),
                'key_changes': len(set(r.get('key') for r in rows if r.get('key')))
            }
        }
    
    def _get_set_info(self, session_id: str = None) -> Optional[Dict]:
        """Obtiene información del set."""
        try:
            from ..mcp_wrapper import AbletonMCPWrapper
            wrapper = AbletonMCPWrapper()
            
            # Intentar obtener manifest
            manifest = wrapper._call_tool('ableton-mcp-ai_get_generation_manifest', {})
            if manifest:
                return manifest
            
            # Fallback a session info
            return wrapper._call_tool('ableton-mcp-ai_get_session_info', {})
        except:
            # Datos de ejemplo
            return self._generate_sample_set_info()
    
    def _generate_sample_set_info(self) -> Dict:
        """Genera información de ejemplo."""
        return {
            'genre': 'techno',
            'bpm': 128,
            'key': 'Am',
            'sections': [
                {'kind': 'intro', 'start_bar': 0, 'end_bar': 16, 'energy': 3, 'bpm': 128},
                {'kind': 'build', 'start_bar': 16, 'end_bar': 32, 'energy': 6, 'bpm': 128},
                {'kind': 'drop', 'start_bar': 32, 'end_bar': 64, 'energy': 9, 'bpm': 128},
                {'kind': 'break', 'start_bar': 64, 'end_bar': 80, 'energy': 5, 'bpm': 128},
                {'kind': 'build', 'start_bar': 80, 'end_bar': 96, 'energy': 7, 'bpm': 128},
                {'kind': 'drop', 'start_bar': 96, 'end_bar': 128, 'energy': 10, 'bpm': 128},
                {'kind': 'outro', 'start_bar': 128, 'end_bar': 144, 'energy': 4, 'bpm': 128},
            ]
        }
    
    def _generate_csv_rows(self, set_info: Dict) -> List[Dict]:
        """Genera filas CSV desde información del set."""
        rows = []
        sections = set_info.get('sections', [])
        
        base_bpm = set_info.get('bpm', 128)
        base_key = set_info.get('key', 'Am')
        genre = set_info.get('genre', 'techno')
        
        for i, section in enumerate(sections):
            start_bar = section.get('start_bar', i * 16)
            end_bar = section.get('end_bar', start_bar + 16)
            duration = end_bar - start_bar
            
            kind = section.get('kind', 'unknown')
            energy = section.get('energy_level', section.get('energy', 5))
            
            row = {
                'track_number': 1,
                'section_type': kind,
                'start_bar': start_bar,
                'end_bar': end_bar,
                'duration_bars': duration,
                'bpm': section.get('bpm', base_bpm),
                'key': section.get('key', base_key),
                'energy_level': energy,
                'drum_pattern': self._get_drum_pattern(kind, genre),
                'bass_type': self._get_bass_type(kind),
                'music_layers': self._count_music_layers(kind, energy),
                'fx_count': self._count_fx(kind),
                'transition_in': 'fade' if i > 0 else 'start',
                'transition_out': 'fade' if i < len(sections) - 1 else 'end',
                'notes': f'Auto-generated {kind} section'
            }
            rows.append(row)
        
        return rows
    
    def _get_drum_pattern(self, section_kind: str, genre: str) -> str:
        """Obtiene patrón de drums según sección."""
        patterns = {
            'intro': 'minimal_hats',
            'build': 'building_snares',
            'drop': 'full_4x4',
            'break': 'reduced_hats',
            'outro': 'fade_out'
        }
        return patterns.get(section_kind, 'standard')
    
    def _get_bass_type(self, section_kind: str) -> str:
        """Obtiene tipo de bass según sección."""
        bass_types = {
            'intro': 'sub_only',
            'build': 'rising_line',
            'drop': 'full_rolling',
            'break': 'minimal_sub',
            'outro': 'fade_sub'
        }
        return bass_types.get(section_kind, 'rolling')
    
    def _count_music_layers(self, section_kind: str, energy: int) -> int:
        """Cuenta capas de música."""
        if section_kind in ['drop']:
            return 3 if energy >= 8 else 2
        elif section_kind in ['build', 'break']:
            return 2
        else:
            return 1
    
    def _count_fx(self, section_kind: str) -> int:
        """Cuenta efectos."""
        fx_counts = {
            'intro': 0,
            'build': 2,  # riser + snare roll
            'drop': 1,   # impact
            'break': 1,  # reverb tail
            'outro': 0
        }
        return fx_counts.get(section_kind, 1)
    
    def _create_csv(self, rows: List[Dict]) -> str:
        """Crea contenido CSV."""
        output = StringIO()
        writer = csv.DictWriter(output, fieldnames=self.CSV_COLUMNS)
        writer.writeheader()
        writer.writerows(rows)
        return output.getvalue()
    
    def _calculate_bpm_range(self, rows: List[Dict]) -> Dict[str, int]:
        """Calcula rango de BPM."""
        bpms = [r.get('bpm', 128) for r in rows if r.get('bpm')]
        return {
            'min': min(bpms) if bpms else 128,
            'max': max(bpms) if bpms else 128,
            'avg': sum(bpms) / len(bpms) if bpms else 128
        }
    
    def _calculate_energy_arc(self, rows: List[Dict]) -> List[Dict]:
        """Calcula arco de energía."""
        return [
            {
                'section': r.get('section_type'),
                'start_bar': r.get('start_bar'),
                'energy': r.get('energy_level')
            }
            for r in rows
        ]


def generate_set_profile_csv() -> Dict[str, Any]:
    """
    T230: Genera perfil CSV del set para exportación pre-show.
    
    Returns:
        Perfil CSV con metadatos del set
    """
    generator = SetProfileGenerator()
    return generator.generate_set_profile()


if __name__ == '__main__':
    # Test del generador
    result = generate_set_profile_csv()
    print(json.dumps(result, indent=2))
    print("\n--- CSV Preview ---")
    print(result.get('csv_preview', 'N/A'))
