"""Async job API for long files."""
import io
import time
import wave


def _wav_bytes(seconds=1.0, rate=16000):
    buf = io.BytesIO()
    with wave.open(buf, "wb") as w:
        w.setnchannels(1)
        w.setsampwidth(2)
        w.setframerate(rate)
        w.writeframes(b"\x00\x00" * int(seconds * rate))
    return buf.getvalue()


def _wait_done(client, headers, job_id, timeout=10.0):
    deadline = time.time() + timeout
    while time.time() < deadline:
        r = client.get(f"/v1/jobs/{job_id}", headers=headers)
        assert r.status_code == 200
        body = r.json()
        if body["status"] in ("done", "error"):
            return body
        time.sleep(0.05)
    raise AssertionError("job did not finish in time")


def test_job_requires_auth(client):
    r = client.post("/v1/jobs",
                    files={"file": ("a.wav", _wav_bytes(), "audio/wav")})
    assert r.status_code == 401


def test_job_lifecycle(client, auth_headers):
    r = client.post("/v1/jobs", headers=auth_headers,
                    files={"file": ("a.wav", _wav_bytes(), "audio/wav")},
                    data={"response_format": "verbose_json"})
    assert r.status_code == 200
    job_id = r.json()["id"]
    assert r.json()["status"] == "queued"

    body = _wait_done(client, auth_headers, job_id)
    assert body["status"] == "done"
    assert body["progress"] == 1.0
    assert body["result"]["text"] == "hello world"


def test_job_404(client, auth_headers):
    assert client.get("/v1/jobs/nope", headers=auth_headers).status_code == 404


def test_job_delete(client, auth_headers):
    r = client.post("/v1/jobs", headers=auth_headers,
                    files={"file": ("a.wav", _wav_bytes(), "audio/wav")})
    job_id = r.json()["id"]
    _wait_done(client, auth_headers, job_id)
    assert client.delete(f"/v1/jobs/{job_id}", headers=auth_headers).status_code == 200
    assert client.get(f"/v1/jobs/{job_id}", headers=auth_headers).status_code == 404


def test_job_queue_cap_rejects_503(client, auth_headers, fake_engine, monkeypatch):
    """Once queue_size pending jobs exist, further submissions get 503 (disk
    exhaustion guard) instead of spooling unbounded uploads."""
    store = client.app.state.store
    monkeypatch.setattr(store, "pending_count", lambda: 8)  # == default queue_size
    r = client.post("/v1/jobs", headers=auth_headers,
                    files={"file": ("a.wav", _wav_bytes(), "audio/wav")})
    assert r.status_code == 503
    assert r.headers.get("Retry-After") == "10"


def test_job_error_when_engine_returns_empty(client, auth_headers, fake_engine):
    fake_engine.service._text = ""  # engine failure contract: ("", {})
    r = client.post("/v1/jobs", headers=auth_headers,
                    files={"file": ("a.wav", _wav_bytes(), "audio/wav")})
    body = _wait_done(client, auth_headers, r.json()["id"])
    assert body["status"] == "error"
