"""
T231: Diversity Dashboard
Integración de get_diversity_memory_stats en dashboard
"""

import json
import os
from datetime import datetime
from typing import Dict, List, Any, Optional
from collections import defaultdict


class DiversityDashboard:
    """
    Dashboard de diversidad de samples.
    
    T231: Visualización de estadísticas de diversidad en dashboard.
    """
    
    def __init__(self):
        self.diversity_file = os.path.join(
            os.path.dirname(os.path.dirname(__file__)),
            'logs', 'diversity_memory.json'
        )
        self.critical_roles = ['kick', 'snare', 'hats', 'bass', 'synth', 'pad']
    
    def get_diversity_memory_stats(self) -> Dict[str, Any]:
        """
        Obtiene estadísticas de la memoria de diversidad.
        
        Returns:
            JSON con:
            - used_families: familias usadas y conteos
            - total_families: número total
            - generation_count: contador
            - file_location: ubicación
            - critical_roles: roles críticos
            - penalty_formula: fórmula de penalización
        """
        # Cargar memoria de diversidad
        diversity_data = self._load_diversity_memory()
        
        # Calcular estadísticas
        used_families = diversity_data.get('used_families', {})
        total_families = diversity_data.get('total_families', len(used_families))
        generation_count = diversity_data.get('generation_count', 0)
        
        # Análisis por rol crítico
        critical_roles_stats = {}
        for role in self.critical_roles:
            families_in_role = {
                k: v for k, v in used_families.items() 
                if k.startswith(f'{role}_')
            }
            
            critical_roles_stats[role] = {
                'total_families': len(families_in_role),
                'total_uses': sum(families_in_role.values()),
                'most_used': max(families_in_role.items(), key=lambda x: x[1]) if families_in_role else None,
                'diversity_score': len(families_in_role) / max(1, sum(families_in_role.values())),
                'health': 'good' if len(families_in_role) >= 3 else 'low' if len(families_in_role) >= 1 else 'critical'
            }
        
        # Calcular fórmula de penalización
        penalty_formula = self._calculate_penalty_formula(used_families)
        
        return {
            'timestamp': datetime.now().isoformat(),
            'used_families': used_families,
            'total_families': total_families,
            'generation_count': generation_count,
            'file_location': self.diversity_file,
            'critical_roles': critical_roles_stats,
            'penalty_formula': penalty_formula,
            'overall_diversity_score': self._calculate_overall_score(used_families),
            'recommendations': self._generate_recommendations(critical_roles_stats)
        }
    
    def _load_diversity_memory(self) -> Dict[str, Any]:
        """Carga memoria de diversidad."""
        if os.path.exists(self.diversity_file):
            try:
                with open(self.diversity_file, 'r') as f:
                    return json.load(f)
            except:
                pass
        
        # Generar datos de ejemplo si no existe
        return self._generate_sample_diversity_data()
    
    def _generate_sample_diversity_data(self) -> Dict[str, Any]:
        """Genera datos de ejemplo de diversidad."""
        families = {}
        
        # Kick families
        families['kick_punchy_001'] = 5
        families['kick_deep_002'] = 3
        families['kick_tech_003'] = 4
        
        # Bass families
        families['bass_rolling_001'] = 6
        families['bass_minimal_002'] = 2
        families['bass_acid_003'] = 3
        
        # Synth families
        families['synth_stab_001'] = 4
        families['synth_pad_002'] = 3
        families['synth_lead_003'] = 2
        
        return {
            'used_families': families,
            'total_families': len(families),
            'generation_count': 15,
            'last_updated': datetime.now().isoformat()
        }
    
    def _calculate_penalty_formula(self, used_families: Dict[str, int]) -> Dict[str, Any]:
        """Calcula fórmula de penalización."""
        if not used_families:
            return {'formula': 'none', 'penalties': {}}
        
        penalties = {}
        
        for family, count in used_families.items():
            # Penalización exponencial basada en uso
            if count <= 2:
                penalty = 0.0
            elif count <= 5:
                penalty = 0.1 * (count - 2)
            else:
                penalty = 0.3 + 0.2 * (count - 5)
            
            penalties[family] = {
                'uses': count,
                'penalty': min(1.0, penalty),
                'selection_probability': max(0.1, 1.0 - penalty)
            }
        
        return {
            'formula': 'exponential_decay',
            'base_threshold': 2,
            'max_penalty': 1.0,
            'penalties': penalties
        }
    
    def _calculate_overall_score(self, used_families: Dict[str, int]) -> float:
        """Calcula score general de diversidad."""
        if not used_families:
            return 0.0
        
        total_uses = sum(used_families.values())
        unique_families = len(used_families)
        
        # Score: familias únicas / usos totales (cuanto más cerca de 1, mejor)
        diversity_ratio = unique_families / max(1, total_uses)
        
        # Normalizar a 0-100
        return min(100, diversity_ratio * 100)
    
    def _generate_recommendations(self, critical_roles_stats: Dict) -> List[str]:
        """Genera recomendaciones basadas en estadísticas."""
        recommendations = []
        
        for role, stats in critical_roles_stats.items():
            if stats['health'] == 'critical':
                recommendations.append(
                    f"CRITICAL: Add more {role} families to the library"
                )
            elif stats['health'] == 'low':
                recommendations.append(
                    f"LOW: Consider adding more variety to {role} samples"
                )
            
            if stats['most_used'] and stats['most_used'][1] > 5:
                recommendations.append(
                    f"WARNING: {role} family '{stats['most_used'][0]}' overused ({stats['most_used'][1]} times)"
                )
        
        return recommendations
    
    def get_coverage_wheel_report(self) -> Dict[str, Any]:
        """
        Obtiene heatmap de uso por carpeta (Coverage Wheel).
        
        Returns:
            JSON con heatmap de carpetas ordenadas por uso
        """
        diversity_data = self._load_diversity_memory()
        used_families = diversity_data.get('used_families', {})
        
        # Agrupar por categoría/carpeta
        folder_usage = defaultdict(lambda: {'files': 0, 'uses': 0})
        
        for family, count in used_families.items():
            # Extraer categoría del nombre de familia
            parts = family.split('_')
            if parts:
                category = parts[0]
                folder_usage[category]['files'] += 1
                folder_usage[category]['uses'] += count
        
        # Ordenar por uso
        sorted_folders = sorted(
            folder_usage.items(),
            key=lambda x: x[1]['uses'],
            reverse=True
        )
        
        return {
            'timestamp': datetime.now().isoformat(),
            'heatmap': [
                {
                    'folder': folder,
                    'unique_files': data['files'],
                    'total_uses': data['uses'],
                    'usage_intensity': 'high' if data['uses'] > 10 else 'medium' if data['uses'] > 5 else 'low',
                    'color': self._get_heatmap_color(data['uses'])
                }
                for folder, data in sorted_folders
            ],
            'total_categories': len(folder_usage),
            'hottest_folder': sorted_folders[0] if sorted_folders else None,
            'coldest_folder': sorted_folders[-1] if sorted_folders else None
        }
    
    def _get_heatmap_color(self, uses: int) -> str:
        """Obtiene color para heatmap."""
        if uses > 15:
            return '#FF4444'  # Rojo (muy usado)
        elif uses > 8:
            return '#FFAA00'  # Naranja
        elif uses > 4:
            return '#FFDD00'  # Amarillo
        elif uses > 0:
            return '#44AA44'  # Verde
        else:
            return '#4444FF'  # Azul (sin uso)
    
    def export_diversity_report(self, format: str = 'json') -> str:
        """Exporta reporte de diversidad."""
        stats = self.get_diversity_memory_stats()
        coverage = self.get_coverage_wheel_report()
        
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        filename = f'diversity_report_{timestamp}.{format}'
        filepath = os.path.join(
            os.path.dirname(os.path.dirname(__file__)),
            'cloud', 'reports', filename
        )
        
        os.makedirs(os.path.dirname(filepath), exist_ok=True)
        
        report = {
            'diversity_stats': stats,
            'coverage_wheel': coverage,
            'generated_at': datetime.now().isoformat()
        }
        
        if format == 'json':
            with open(filepath, 'w') as f:
                json.dump(report, f, indent=2)
        elif format == 'html':
            self._export_html_report(report, filepath)
        
        return filepath
    
    def _export_html_report(self, report: Dict, filepath: str):
        """Exporta reporte HTML."""
        html = f'''
<!DOCTYPE html>
<html>
<head>
    <title>Diversity Report - AbletonMCP-AI</title>
    <style>
        body {{ font-family: Arial, sans-serif; background: #1a1a1a; color: #fff; padding: 20px; }}
        .container {{ max-width: 1000px; margin: 0 auto; }}
        h1 {{ color: #4CAF50; }}
        .metric {{ background: #2a2a2a; padding: 15px; margin: 10px 0; border-radius: 8px; }}
        .metric h3 {{ margin-top: 0; color: #888; }}
        .score {{ font-size: 36px; color: #4CAF50; }}
        .heatmap {{ display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; }}
        .folder {{ padding: 10px; border-radius: 4px; color: #000; font-weight: bold; }}
        .recommendations {{ background: #3a3a3a; padding: 15px; border-left: 4px solid #FFAA00; }}
    </style>
</head>
<body>
    <div class="container">
        <h1>🎵 Diversity Memory Report</h1>
        <div class="metric">
            <h3>Overall Diversity Score</h3>
            <div class="score">{report['diversity_stats'].get('overall_diversity_score', 0):.1f}/100</div>
        </div>
        <div class="metric">
            <h3>Total Families Used</h3>
            <div class="score">{report['diversity_stats'].get('total_families', 0)}</div>
        </div>
        <div class="heatmap">
            {''.join(f'<div class="folder" style="background: {f["color"]}">{f["folder"]} ({f["uses"]})</div>' for f in report['coverage_wheel'].get('heatmap', []))}
        </div>
        <div class="recommendations">
            <h3>Recommendations</h3>
            <ul>
                {''.join(f'<li>{r}</li>' for r in report['diversity_stats'].get('recommendations', []))}
            </ul>
        </div>
    </div>
</body>
</html>
'''
        with open(filepath, 'w', encoding='utf-8') as f:
            f.write(html)


def get_diversity_memory_stats() -> Dict[str, Any]:
    """
    T231: Obtiene estadísticas de diversidad de samples.
    
    Returns:
        JSON con estadísticas completas de diversidad
    """
    dashboard = DiversityDashboard()
    return dashboard.get_diversity_memory_stats()


def get_coverage_wheel_report() -> Dict[str, Any]:
    """
    Obtiene heatmap de coverage wheel.
    
    Returns:
        JSON con heatmap de carpetas
    """
    dashboard = DiversityDashboard()
    return dashboard.get_coverage_wheel_report()


if __name__ == '__main__':
    # Test del dashboard
    stats = get_diversity_memory_stats()
    print("Diversity Stats:")
    print(json.dumps(stats, indent=2))
    
    print("\nCoverage Wheel:")
    coverage = get_coverage_wheel_report()
    print(json.dumps(coverage, indent=2))
