import numpy as np
from scipy.signal import butter, sosfilt
from .base import BaseProcessorModule

class EqModule(BaseProcessorModule):
    """Equalization Module with functional Crossover-based EQ."""
    
    def process(self, audio: np.ndarray, **kwargs) -> np.ndarray:
        return audio

    def apply_dynamic_eq(self, audio: np.ndarray, settings: list) -> np.ndarray:
        """
        Apply EQ bands. Currently implements static EQ functionality.
        Uses crossover-splitting for clean shelving/peaking effects.
        """
        if not settings: return audio
        
        sr = self.sample_rate
        out = audio.copy()
        
        for band in settings:
            enabled = band.get('enabled', True)
            if not enabled: continue
            
            freq = band['freq_hz']
            gain_db = band.get('gain_db', 0.0)
            f_type = band.get('filter_type', 'bell')
            mode = band.get('mode', 'normal')
            
            if abs(gain_db) < 0.1: continue

            # Calculate linear gain
            gain_lin = 10 ** (gain_db / 20.0)
            
            # --- 1. HIGH SHELF (Boost or Cut) ---
            if f_type == 'high_shelf' or (mode == 'shelf' and freq > 1000):
                # Split signal at freq
                sos_hp = butter(2, freq, 'hp', fs=sr, output='sos')
                high_content = sosfilt(sos_hp, out, axis=0)
                
                sos_lp = butter(2, freq, 'lp', fs=sr, output='sos')
                low_content = sosfilt(sos_lp, out, axis=0)
                
                # Apply gain to high content only
                out = low_content + (high_content * gain_lin)
            
            # --- 2. LOW SHELF (Boost or Cut) ---
            elif f_type == 'low_shelf' or (mode == 'shelf' and freq < 1000):
                # Split signal
                sos_hp = butter(2, freq, 'hp', fs=sr, output='sos')
                high_content = sosfilt(sos_hp, out, axis=0)
                
                sos_lp = butter(2, freq, 'lp', fs=sr, output='sos')
                low_content = sosfilt(sos_lp, out, axis=0)
                
                # Apply gain to low content only
                out = (low_content * gain_lin) + high_content

            # --- 3. BELL / PEAK (Default) ---
            else:
                # Standard Parametric EQ Band
                q = band.get('q', 1.0)
                bw_hz = freq / q
                low_cut = max(20, freq - (bw_hz/2))
                high_cut = min(sr/2 - 1, freq + (bw_hz/2))
                
                # Bandpass isolation
                sos_bp = butter(2, [low_cut, high_cut], 'bandpass', fs=sr, output='sos')
                band_content = sosfilt(sos_bp, out, axis=0)
                
                # Apply gain difference
                # If we want 3dB boost (1.4x), we add 0.4x of band.
                # If we want -3dB cut (0.7x), we subtract 0.3x of band.
                
                # Formula: out = original + (band * (gain - 1))
                adjustment = gain_lin - 1.0
                out = out + (band_content * adjustment)
                
        return out
