"""BPM Analyzer using Librosa for accurate tempo detection."""
import os
import librosa
import numpy as np
from typing import Dict, Tuple, Optional
import logging

logger = logging.getLogger(__name__)

class BPMAnalyzer:
    """Analyzes BPM of audio files using librosa beat tracking."""
    
    def __init__(self, min_bpm: float = 60.0, max_bpm: float = 200.0):
        self.min_bpm = min_bpm
        self.max_bpm = max_bpm
    
    def analyze_bpm(self, audio_path: str) -> Tuple[float, float]:
        """
        Analyze BPM of audio file.
        
        Returns:
            (bpm, confidence) - tempo and confidence score (0.0-1.0)
        """
        try:
            # Load audio
            y, sr = librosa.load(audio_path, duration=30.0)  # First 30s for speed
            
            # Get tempo
            tempo, beat_frames = librosa.beat.beat_track(y=y, sr=sr)
            
            # Calculate confidence based on beat strength
            onset_env = librosa.onset.onset_strength(y=y, sr=sr)
            confidence = np.mean(onset_env) / np.max(onset_env) if np.max(onset_env) > 0 else 0.5
            
            # Handle tempo doubling/halving
            if tempo < self.min_bpm:
                tempo = tempo * 2
            elif tempo > self.max_bpm:
                tempo = tempo / 2
                
            return float(tempo), float(confidence)
            
        except Exception as e:
            logger.error(f"Error analyzing {audio_path}: {e}")
            return 0.0, 0.0
    
    def analyze_all_library(self, library_path: str, progress_callback=None) -> Dict[str, dict]:
        """
        Batch analyze all samples in library.
        
        Args:
            library_path: Root path to sample library
            progress_callback: Optional function(current, total) for progress
            
        Returns:
            Dict mapping {path: {"bpm": float, "confidence": float}}
        """
        results = {}
        
        # Find all audio files
        audio_exts = ('.wav', '.aif', '.aiff', '.mp3', '.flac')
        audio_files = []
        
        for root, dirs, files in os.walk(library_path):
            for f in files:
                if f.lower().endswith(audio_exts):
                    audio_files.append(os.path.join(root, f))
        
        total = len(audio_files)
        
        for i, path in enumerate(audio_files):
            bpm, confidence = self.analyze_bpm(path)
            
            results[path] = {
                "bpm": bpm,
                "confidence": confidence,
                "analyzed_at": str(np.datetime64('now'))
            }
            
            if progress_callback:
                progress_callback(i + 1, total)
        
        return results
    
    def get_bpm_pool(self, target_bpm: float, tolerance: float = 5.0) -> Dict[str, dict]:
        """Get samples within BPM tolerance from metadata store."""
        # This will be implemented with metadata_store integration
        pass


# Convenience function
def analyze_sample(audio_path: str) -> Tuple[float, float]:
    """Quick BPM analysis of single sample."""
    analyzer = BPMAnalyzer()
    return analyzer.analyze_bpm(audio_path)
