from __future__ import annotations

import queue
import threading
import time

from engine.batch_worker import BatchProcessingThread


def _thread(files):
    return BatchProcessingThread(
        file_list=files,
        output_dir="/tmp",
        output_pattern="{name}_mastered.wav",
        preset_name="EDM",
        preset_values={},
        active_modules={},
        message_queue=queue.Queue(),
    )


def test_remote_batch_uses_at_most_three_concurrent_lanes(monkeypatch):
    monkeypatch.delenv("AUTOREMASTER_REMOTE_WORKER", raising=False)
    monkeypatch.delenv("AUTOMASTER_FORCE_LOCAL", raising=False)
    batch = _thread([f"track-{i}.wav" for i in range(7)])
    lock = threading.Lock()
    active = 0
    peak = 0

    def fake_process(path, idx, total):
        nonlocal active, peak
        with lock:
            active += 1
            peak = max(peak, active)
        time.sleep(0.08)
        with lock:
            active -= 1
        return f"/tmp/out-{idx}.wav"

    monkeypatch.setattr(batch, "_process_file", fake_process)
    started = time.monotonic()
    batch.run()
    elapsed = time.monotonic() - started

    assert peak == 3
    assert elapsed < 0.45  # sequential would be ~0.56 s
    messages = list(batch.message_queue.queue)
    complete = [data for kind, data in messages if kind == "batch_complete"][-1]
    assert complete == {"processed": 7, "errors": 0}


def test_pause_waits_before_starting_additional_files(monkeypatch):
    monkeypatch.delenv("AUTOREMASTER_REMOTE_WORKER", raising=False)
    monkeypatch.delenv("AUTOMASTER_FORCE_LOCAL", raising=False)
    batch = _thread([f"track-{i}.wav" for i in range(6)])
    release = threading.Event()
    first_wave = threading.Event()
    lock = threading.Lock()
    started_indices = []

    def fake_process(path, idx, total):
        with lock:
            started_indices.append(idx)
            if len(started_indices) >= 3:
                first_wave.set()
        release.wait(timeout=2)
        return f"/tmp/out-{idx}.wav"

    monkeypatch.setattr(batch, "_process_file", fake_process)
    batch.start()
    assert first_wave.wait(timeout=2)
    batch.pause()
    release.set()
    time.sleep(0.12)
    with lock:
        assert len(started_indices) == 3
    batch.resume()
    batch.join(timeout=3)
    assert not batch.is_alive()
    with lock:
        assert sorted(started_indices) == list(range(6))


def test_worker_mode_remains_sequential(monkeypatch):
    monkeypatch.setenv("AUTOREMASTER_REMOTE_WORKER", "1")
    batch = _thread(["a.wav", "b.wav", "c.wav"])
    lock = threading.Lock()
    active = 0
    peak = 0

    def fake_process(path, idx, total):
        nonlocal active, peak
        with lock:
            active += 1
            peak = max(peak, active)
        time.sleep(0.02)
        with lock:
            active -= 1
        return f"/tmp/{idx}.wav"

    monkeypatch.setattr(batch, "_process_file", fake_process)
    batch.run()
    assert peak == 1
