"""Unit tests for applyCompression function."""
import unittest
from pathlib import Path
import numpy as np
import soundfile as sf
from reaper_mcp.audio.audio_processing import apply_compression
from tests.base import TempDirTestCase


class TestApplyCompression(TempDirTestCase):
    """Tests for the apply_compression function."""
    
    def setUp(self):
        """Set up test fixtures."""
        super().setUp()
        self.test_file = self.temp_dir / "test_audio.wav"
        
        # Create a test audio file with varying amplitude
        sample_rate = 44100
        duration = 2.0
        t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
        # Create audio with varying amplitude (quiet then loud)
        envelope = np.concatenate([
            np.linspace(0.1, 0.1, sample_rate),
            np.linspace(0.9, 0.9, sample_rate)
        ])
        audio = envelope * np.sin(2 * np.pi * 440.0 * t)
        sf.write(self.test_file, audio, sample_rate)
    
    def test_apply_compression_basic(self):
        """Test basic compression."""
        result = apply_compression(
            self.test_file,
            threshold=-20.0,
            ratio=4.0,
            attack=0.005,
            release=0.1
        )
        
        self.assertNotIn("error", result)
        self.assertIn("file_path", result)
        self.assertTrue(Path(result["file_path"]).exists())
        
        # Verify compression reduces dynamic range
        original_audio, _ = sf.read(self.test_file)
        compressed_audio, _ = sf.read(result["file_path"])
        
        # Original should have wider dynamic range
        original_range = np.max(np.abs(original_audio)) - np.min(np.abs(original_audio[original_audio != 0]))
        compressed_range = np.max(np.abs(compressed_audio)) - np.min(np.abs(compressed_audio[compressed_audio != 0]))
        
        # Compression should reduce the range (though not always guaranteed with simple signals)
        # At minimum, check that output exists and is valid
        self.assertGreater(len(compressed_audio), 0)
        
        # Clean up
        Path(result["file_path"]).unlink()
    
    def test_apply_compression_high_ratio(self):
        """Test compression with high ratio (limiting)."""
        result = apply_compression(
            self.test_file,
            threshold=-10.0,
            ratio=10.0,
            attack=0.001,
            release=0.05
        )
        
        self.assertNotIn("error", result)
        self.assertTrue(Path(result["file_path"]).exists())
        
        # Clean up
        Path(result["file_path"]).unlink()
    
    def test_apply_compression_gentle(self):
        """Test gentle compression."""
        result = apply_compression(
            self.test_file,
            threshold=-30.0,
            ratio=2.0,
            attack=0.01,
            release=0.2
        )
        
        self.assertNotIn("error", result)
        self.assertTrue(Path(result["file_path"]).exists())
        
        # Clean up
        Path(result["file_path"]).unlink()
    
    def test_apply_compression_fast_attack(self):
        """Test compression with fast attack."""
        result = apply_compression(
            self.test_file,
            threshold=-15.0,
            ratio=4.0,
            attack=0.001,
            release=0.1
        )
        
        self.assertNotIn("error", result)
        self.assertTrue(Path(result["file_path"]).exists())
        
        # Clean up
        Path(result["file_path"]).unlink()
    
    def test_apply_compression_nonexistent_file(self):
        """Test applying compression to nonexistent file."""
        result = apply_compression("/nonexistent/file.wav")
        
        self.assertIn("error", result)
