"""
Metrics and Evaluation Utilities
"""

import numpy as np
from typing import Dict, List


def compute_metrics(predictions: np.ndarray, targets: np.ndarray) -> Dict[str, float]:
    """Compute classification metrics."""
    predictions = predictions.flatten()
    targets = targets.flatten()
    pred_binary = (predictions > 0.5).astype(int)
    
    accuracy = np.mean(pred_binary == targets)
    tp = np.sum((pred_binary == 1) & (targets == 1))
    fp = np.sum((pred_binary == 1) & (targets == 0))
    fn = np.sum((pred_binary == 0) & (targets == 1))
    
    precision = tp / (tp + fp + 1e-8)
    recall = tp / (tp + fn + 1e-8)
    f1 = 2 * precision * recall / (precision + recall + 1e-8)
    
    eps = 1e-8
    loss = -np.mean(targets * np.log(predictions + eps) + (1 - targets) * np.log(1 - predictions + eps))
    
    return {'accuracy': float(accuracy), 'precision': float(precision), 
            'recall': float(recall), 'f1': float(f1), 'loss': float(loss)}


def information_metrics(distribution: np.ndarray) -> Dict[str, float]:
    """Compute information-theoretic metrics."""
    dist = np.abs(distribution.flatten()) + 1e-10
    dist = dist / np.sum(dist)
    entropy = -np.sum(dist * np.log(dist))
    effective_dim = np.exp(entropy)
    
    return {'entropy': float(entropy), 'effective_dim': float(effective_dim),
            'max_value': float(np.max(distribution)), 'mean_value': float(np.mean(distribution))}


def convergence_metrics(history: List[float], window: int = 10) -> Dict[str, float]:
    """Compute convergence metrics from training history."""
    if len(history) < window:
        return {'converged': False, 'rate': 0.0, 'stability': 0.0}
    
    recent = history[-window:]
    early = history[:window] if len(history) >= 2 * window else history[:len(history)//2]
    
    improvement = (np.mean(early) - np.mean(recent)) / (np.mean(early) + 1e-8)
    stability = 1 / (np.var(recent) + 1e-8)
    stability = np.clip(stability, 0, 100)
    converged = stability > 10 and improvement > 0.1
    
    return {'converged': converged, 'rate': float(improvement), 'stability': float(stability)}
