"""The "multi_attachment" form field: a list of uploaded files' ids, checked
on submit against real uploads and the field's max_files / max_file_size_mb
(app/crud/form_integrity.py) — plus the form's review_before_submit setting
round-tripping through the API."""

import uuid


async def _form(client, headers, field: dict, settings: dict | None = None) -> dict:
    resp = await client.post(
        "/forms",
        headers=headers,
        json={"name": f"Pytest Attachments {uuid.uuid4().hex[:6]}", "field_definitions": [field], "settings": settings or {}},
    )
    assert resp.status_code == 201, resp.text
    published = await client.post(f"/forms/{resp.json()['form_id']}/publish", headers=headers)
    assert published.status_code == 200
    return published.json()


async def _upload(client, headers, name: str, data: bytes) -> str:
    resp = await client.post("/uploads", headers=headers, files={"file": (name, data, "application/octet-stream")})
    assert resp.status_code == 201
    return resp.json()["id"]


async def _submit(client, headers, form: dict, value):
    return await client.post(
        "/form-submissions",
        headers=headers,
        json={"form_id": form["form_id"], "form_version": form["version"], "field_values": {"docs": value}},
    )


async def test_multi_attachment_accepts_uploaded_files(client, auth_headers):
    form = await _form(client, auth_headers, {"name": "docs", "type": "multi_attachment", "label": "Documents", "required": True, "max_files": 3})
    ids = [await _upload(client, auth_headers, f"doc{i}.pdf", b"%PDF-1.4 sample") for i in range(2)]

    resp = await _submit(client, auth_headers, form, ids)
    assert resp.status_code == 201, resp.text
    assert resp.json()["field_values"]["docs"] == ids

    # Required: an empty list is a blank answer.
    resp = await _submit(client, auth_headers, form, [])
    assert resp.status_code == 422


async def test_multi_attachment_limits(client, auth_headers):
    form = await _form(
        client, auth_headers, {"name": "docs", "type": "multi_attachment", "label": "Documents", "max_files": 2, "max_file_size_mb": 0.001}
    )
    small = [await _upload(client, auth_headers, f"s{i}.txt", b"tiny") for i in range(3)]
    big = await _upload(client, auth_headers, "big.bin", b"x" * 5000)

    too_many = await _submit(client, auth_headers, form, small)
    assert too_many.status_code == 422
    assert "at most 2 files" in too_many.text

    too_big = await _submit(client, auth_headers, form, [small[0], big])
    assert too_big.status_code == 422
    assert "larger than" in too_big.text

    not_uploaded = await _submit(client, auth_headers, form, [str(uuid.uuid4())])
    assert not_uploaded.status_code == 422
    assert "isn't uploaded" in not_uploaded.text

    not_a_list = await _submit(client, auth_headers, form, small[0])
    assert not_a_list.status_code == 422


async def test_review_before_submit_setting_round_trips(client, auth_headers):
    form = await _form(
        client,
        auth_headers,
        {"name": "docs", "type": "multi_attachment", "label": "Documents"},
        {"review_before_submit": True, "review_title": "Check your application"},
    )
    live = await client.get(f"/forms/{form['form_id']}/live", headers=auth_headers)
    assert live.status_code == 200
    assert live.json()["settings"]["review_before_submit"] is True
    assert live.json()["settings"]["review_title"] == "Check your application"
