"""Unit tests for _analyze_audio_data function."""
import unittest
import numpy as np
import soundfile as sf
from pathlib import Path

from reaper_mcp.audio.audio_analysis import _analyze_audio_data
from tests.base import TempDirTestCase


class TestAnalyzeAudioData(TempDirTestCase):
    """Tests for the _analyze_audio_data function."""
    
    def setUp(self):
        """Set up test parameters."""
        super().setUp()
        self.sample_rate = 44100
        self.duration = 2.0
        self.test_file = self.temp_dir / "test_audio.wav"
    
    def _generate_tone(self, frequency: float) -> np.ndarray:
        """Generate a simple sine wave tone."""
        t = np.linspace(0, self.duration, int(self.sample_rate * self.duration), endpoint=False)
        return 0.5 * np.sin(2 * np.pi * frequency * t)
    
    def test_analyze_audio_data_mono(self):
        """Test analysis of mono audio data."""
        audio = self._generate_tone(440.0)
        
        # Create a temporary file for testing
        sf.write(self.test_file, audio, self.sample_rate)
        
        metadata = _analyze_audio_data(audio, self.sample_rate, self.test_file)
        
        # Check that all required fields are present
        self.assertIn("file_path", metadata)
        self.assertIn("duration", metadata)
        self.assertIn("sample_rate", metadata)
        self.assertIn("channels", metadata)
        self.assertIn("rms_energy", metadata)
        self.assertIn("peak_amplitude", metadata)
        self.assertIn("zero_crossing_rate", metadata)
        self.assertIn("estimated_tempo_bpm", metadata)
        self.assertIn("estimated_key", metadata)
        self.assertIn("mtime", metadata)
        
        # Check values
        self.assertEqual(metadata["sample_rate"], self.sample_rate)
        self.assertEqual(metadata["channels"], 1)
        self.assertAlmostEqual(metadata["duration"], self.duration, places=2)
        self.assertGreater(metadata["rms_energy"], 0)
        self.assertLessEqual(metadata["peak_amplitude"], 1.0)
        self.assertEqual(metadata["estimated_key"], "A")
    
    def test_analyze_audio_data_stereo(self):
        """Test analysis of stereo audio data."""
        audio_mono = self._generate_tone(440.0)
        # Create stereo by duplicating mono
        audio_stereo = np.column_stack([audio_mono, audio_mono])
        
        # Create a temporary file for testing
        sf.write(self.test_file, audio_stereo, self.sample_rate)
        
        metadata = _analyze_audio_data(audio_stereo, self.sample_rate, self.test_file)
        
        # Check channels
        self.assertEqual(metadata["channels"], 2)
        self.assertEqual(metadata["estimated_key"], "A")
    
    def test_analyze_audio_data_rms_energy(self):
        """Test RMS energy calculation."""
        audio = self._generate_tone(440.0)
        sf.write(self.test_file, audio, self.sample_rate)
        
        metadata = _analyze_audio_data(audio, self.sample_rate, self.test_file)
        
        # For a 0.5 amplitude sine wave, RMS should be approximately 0.5/sqrt(2) ≈ 0.354
        expected_rms = 0.5 / np.sqrt(2)
        self.assertAlmostEqual(metadata["rms_energy"], expected_rms, places=2)
    
    def test_analyze_audio_data_peak_amplitude(self):
        """Test peak amplitude detection."""
        audio = self._generate_tone(440.0)
        sf.write(self.test_file, audio, self.sample_rate)
        
        metadata = _analyze_audio_data(audio, self.sample_rate, self.test_file)
        
        # Peak should be close to 0.5 (our amplitude)
        self.assertAlmostEqual(metadata["peak_amplitude"], 0.5, places=2)
