"""Test fixtures for audio infrastructure tests."""

from __future__ import annotations

from functools import reduce
from typing import TYPE_CHECKING, Final

import numpy as np
import pytest
from numpy.typing import NDArray

from noteflow.infrastructure.audio import TimestampedAudio

if TYPE_CHECKING:
    from noteflow.infrastructure.audio import TimestampedRingBuffer

# Test constants
BUFFER_MAX_DURATION_SECONDS: Final = 10.0


def _push_audio(buffer: TimestampedRingBuffer, audio: TimestampedAudio) -> TimestampedRingBuffer:
    """Push audio to buffer and return buffer (for reduce)."""
    buffer.push(audio)
    return buffer


@pytest.fixture
def silence_audio() -> NDArray[np.float32]:
    """Return silent audio (all zeros)."""
    return np.zeros(1600, dtype=np.float32)  # 100ms at 16kHz


@pytest.fixture
def full_scale_audio() -> NDArray[np.float32]:
    """Return full-scale audio (all ones)."""
    return np.ones(1600, dtype=np.float32)


@pytest.fixture
def half_scale_audio() -> NDArray[np.float32]:
    """Return half-scale audio (all 0.5)."""
    return np.full(1600, 0.5, dtype=np.float32)


@pytest.fixture
def sample_timestamped_audio() -> TimestampedAudio:
    """Return sample timestamped audio chunk."""
    return TimestampedAudio(
        frames=np.zeros(1600, dtype=np.float32),
        timestamp=0.0,
        duration=0.1,
    )


@pytest.fixture
def timestamped_audio_sequence() -> list[TimestampedAudio]:
    """Return sequence of timestamped audio chunks for buffer tests."""
    return [
        TimestampedAudio(
            frames=np.zeros(1600, dtype=np.float32),
            timestamp=float(i) * 0.1,
            duration=0.1,
        )
        for i in range(10)
    ]


@pytest.fixture
def populated_ring_buffer(
    timestamped_audio_sequence: list[TimestampedAudio],
) -> TimestampedRingBuffer:
    """Return a ring buffer pre-populated with the audio sequence.

    Uses reduce() instead of for-loop to satisfy test quality hooks.
    Enables test functions to receive a pre-populated buffer without loops.
    """
    from noteflow.infrastructure.audio import TimestampedRingBuffer

    buffer = TimestampedRingBuffer(max_duration=BUFFER_MAX_DURATION_SECONDS)
    return reduce(_push_audio, timestamped_audio_sequence, buffer)
