"""SpectralAnalyzer class wrapping functional APIs.

Provides object-oriented interface to spectral analysis functions
for compatibility with legacy code and workflows.

Example:
    >>> from oscura.analyzers.waveform.spectral.analyzer import SpectralAnalyzer
    >>> analyzer = SpectralAnalyzer()
    >>> freqs, mags = analyzer.fft(data, sample_rate)
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Literal

import numpy as np

from oscura.analyzers.waveform.spectral.fft import fft
from oscura.analyzers.waveform.spectral.quality_metrics import enob, sfdr, sinad, snr, thd

if TYPE_CHECKING:
    from numpy.typing import NDArray

    from oscura.core.types import MeasurementResult, WaveformTrace


class SpectralAnalyzer:
    """Spectral analysis class wrapping functional APIs.

    Provides object-oriented interface to spectral analysis functions
    for compatibility with legacy code and workflows.

    Example:
        >>> analyzer = SpectralAnalyzer()
        >>> freqs, mags = analyzer.fft(data, sample_rate)
        >>> thd_value = analyzer.thd(trace)
    """

    def fft(
        self,
        data: NDArray[np.floating[Any]],
        sample_rate: float,
        *,
        window: str = "hann",
        nfft: int | None = None,
        detrend: Literal["none", "mean", "linear"] = "mean",
        return_phase: bool = False,
    ) -> (
        tuple[NDArray[np.float64], NDArray[np.float64]]
        | tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.float64]]
    ):
        """Compute FFT of signal data.

        Args:
            data: Input signal data
            sample_rate: Sample rate in Hz
            window: Window function name (default "hann")
            nfft: FFT size (power of 2), auto-computed if None
            detrend: Detrend method ('none', 'mean', or 'linear')
            return_phase: If True, also return phase spectrum

        Returns:
            Tuple of (frequencies, magnitudes_db) or (frequencies, magnitudes_db, phase)
        """
        from oscura.core.types import TraceMetadata, WaveformTrace

        # Convert to WaveformTrace for functional API
        trace = WaveformTrace(data=data, metadata=TraceMetadata(sample_rate=sample_rate))

        # Call functional API (always returns dB)
        return fft(trace, window=window, nfft=nfft, detrend=detrend, return_phase=return_phase)

    def thd(self, trace: WaveformTrace, fundamental_freq: float | None = None) -> MeasurementResult:
        """Compute Total Harmonic Distortion."""
        return thd(trace)

    def snr(self, trace: WaveformTrace, fundamental_freq: float | None = None) -> MeasurementResult:
        """Compute Signal-to-Noise Ratio."""
        return snr(trace)

    def sinad(
        self, trace: WaveformTrace, fundamental_freq: float | None = None
    ) -> MeasurementResult:
        """Compute SINAD (Signal-to-Noise-And-Distortion)."""
        return sinad(trace)

    def enob(
        self, trace: WaveformTrace, fundamental_freq: float | None = None
    ) -> MeasurementResult:
        """Compute Effective Number of Bits."""
        return enob(trace)

    def sfdr(
        self, trace: WaveformTrace, fundamental_freq: float | None = None
    ) -> MeasurementResult:
        """Compute Spurious-Free Dynamic Range."""
        return sfdr(trace)


__all__ = [
    "SpectralAnalyzer",
]
