import sys
import shutil
import pytest
import subprocess
import time
import requests
from pathlib import Path

SERVER_PORT = 8800
SERVER_URL = f'http://localhost:{SERVER_PORT}'
HERE = Path(__file__).parent.parent


@pytest.fixture(scope='session')
def server():
    uv = shutil.which('uv')
    if uv:
        cmd = [uv, 'run', 'python', '-m', 'uvicorn', 'server:app', '--host', '0.0.0.0', '--port', str(SERVER_PORT)]
    else:
        cmd = [sys.executable, '-m', 'uvicorn', 'server:app', '--host', '0.0.0.0', '--port', str(SERVER_PORT)]
    proc = subprocess.Popen(cmd, cwd=HERE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    for _ in range(30):
        try:
            resp = requests.get(f'{SERVER_URL}/api/ping', timeout=2)
            if resp.ok:
                break
        except requests.ConnectionError:
            time.sleep(0.5)
    else:
        proc.terminate()
        raise RuntimeError('Server did not start in time')

    yield SERVER_URL

    proc.terminate()
    proc.wait()


@pytest.fixture
def sample_wav():
    """Generate a minimal valid WAV file (sine tone, 44100, 16-bit mono, 0.5s)."""
    import struct
    import math

    sr = 44100
    bits = 16
    channels = 1
    duration = 0.5
    num_samples = int(sr * duration)

    samples = []
    for i in range(num_samples):
        val = int(math.sin(2 * math.pi * 440 * i / sr) * 0.3 * 32767)
        samples.append(struct.pack('<h', val))

    data = b''.join(samples)
    data_size = len(data)
    file_size = 36 + data_size

    buf = bytearray()
    buf += b'RIFF'
    buf += struct.pack('<I', file_size)
    buf += b'WAVE'
    buf += b'fmt '
    buf += struct.pack('<I', 16)  # chunk size
    buf += struct.pack('<H', 1)   # PCM
    buf += struct.pack('<H', channels)
    buf += struct.pack('<I', sr)
    buf += struct.pack('<I', sr * channels * bits // 8)  # byte rate
    buf += struct.pack('<H', channels * bits // 8)  # block align
    buf += struct.pack('<H', bits)
    buf += b'data'
    buf += struct.pack('<I', data_size)
    buf += data

    return ('tone_440.wav', bytes(buf))


@pytest.fixture
def sample_wav_kick(sample_wav):
    """Rename to look like a kick sample."""
    name, data = sample_wav
    return ('kick_808.wav', data)


@pytest.fixture
def page(browser, server):
    ctx = browser.new_context(viewport={'width': 1280, 'height': 800})
    page = ctx.new_page()
    page.goto(server)
    yield page
    ctx.close()
