"""Quick microphone tests. Run: uv run python test_mic.py"""

import numpy as np
import sounddevice as sd
import sys
import time

SAMPLE_RATE = 16000


def test_device_info():
    """Show which device will be used for recording."""
    default_input = sd.default.device[0]
    info = sd.query_devices(default_input)
    print(f"Default input device [{default_input}]: {info['name']}")
    print(f"  Max input channels: {info['max_input_channels']}")
    print(f"  Default sample rate: {info['default_samplerate']}")
    assert info["max_input_channels"] > 0, "Default device has no input channels!"
    print("  PASS\n")


def test_record_1s():
    """Record 1 second and check we got non-silent audio."""
    print("Recording 1 second... (speak or make noise!)")
    audio = sd.rec(SAMPLE_RATE, samplerate=SAMPLE_RATE, channels=1, dtype="float32")
    sd.wait()
    audio = audio.flatten()

    peak = np.max(np.abs(audio))
    rms = np.sqrt(np.mean(audio ** 2))
    print(f"  Samples: {len(audio)}")
    print(f"  Peak amplitude: {peak:.4f}")
    print(f"  RMS: {rms:.6f}")

    assert len(audio) == SAMPLE_RATE, f"Expected {SAMPLE_RATE} samples, got {len(audio)}"
    assert peak > 0, "All zeros — mic not capturing anything"
    if peak < 0.001:
        print("  WARNING: Very low signal — mic might be muted or too far away")
    else:
        print("  Signal level looks good")
    print("  PASS\n")


def test_record_levels():
    """Record 3 seconds in 1-second chunks, show live levels."""
    print("Recording 3 seconds — speak during seconds 2-3 for comparison...")
    for i in range(3):
        audio = sd.rec(SAMPLE_RATE, samplerate=SAMPLE_RATE, channels=1, dtype="float32")
        sd.wait()
        audio = audio.flatten()
        rms = np.sqrt(np.mean(audio ** 2))
        peak = np.max(np.abs(audio))
        bar = "#" * int(min(peak * 200, 50))
        print(f"  Second {i+1}: peak={peak:.4f} rms={rms:.6f} |{bar}")
    print("  PASS\n")


def test_stream_callback():
    """Test that InputStream callback fires correctly."""
    frames_received = []

    def callback(indata, frames, time_info, status):
        if status:
            print(f"  Status: {status}")
        frames_received.append(len(indata))

    print("Testing InputStream callback for 1 second...")
    with sd.InputStream(samplerate=SAMPLE_RATE, channels=1, dtype="float32",
                        callback=callback, blocksize=800):
        time.sleep(1)

    total_frames = sum(frames_received)
    expected = SAMPLE_RATE
    print(f"  Callbacks fired: {len(frames_received)}")
    print(f"  Total frames: {total_frames} (expected ~{expected})")
    print(f"  Blocksize per callback: {frames_received[0] if frames_received else 'N/A'}")
    assert len(frames_received) > 0, "No callbacks received!"
    assert abs(total_frames - expected) < expected * 0.2, f"Frame count off by >20%"
    print("  PASS\n")


if __name__ == "__main__":
    print("=== Microphone Tests ===\n")
    test_device_info()
    test_record_1s()
    test_record_levels()
    test_stream_callback()
    print("All tests passed!")
