from __future__ import annotations

import time

import fitz
import pytest

from .conftest import TenantSeed
from .helpers import ReleaseApiClient


def _document_ids(items: list[dict]) -> set[int]:
    return {int(item["documentId"]) for item in items if item.get("documentId") is not None}


def _sample_pdf_bytes(text: str) -> bytes:
    document = fitz.open()
    page = document.new_page()
    page.insert_text((72, 72), text)
    return document.tobytes()


@pytest.mark.release
def test_g4_document_list_and_detail_respect_tenant_boundary(
    tenant_admin_api: ReleaseApiClient,
    tenant_admin_api_b: ReleaseApiClient,
    tenant_a: TenantSeed,
    tenant_b: TenantSeed,
    make_release_document,
) -> None:
    own_doc = make_release_document(
        client=tenant_admin_api,
        tenant=tenant_a,
        file_name=f"pytest-g4-a-{int(time.time())}.txt",
    )
    other_doc = make_release_document(
        client=tenant_admin_api_b,
        tenant=tenant_b,
        file_name=f"pytest-g4-b-{int(time.time())}.txt",
    )

    own_list = ReleaseApiClient.json_data(tenant_admin_api.get("/api/documents/list?page=1&pageSize=100"))
    own_ids = _document_ids(own_list["documents"])
    assert own_doc.document_id in own_ids
    assert other_doc.document_id not in own_ids

    own_detail = ReleaseApiClient.json_data(tenant_admin_api.get(f"/api/documents/{own_doc.document_id}"))
    assert int(own_detail["documentId"]) == own_doc.document_id
    assert str(own_detail.get("tenantCode") or "") == tenant_a.tenant_code

    cross_detail = tenant_admin_api.get(f"/api/documents/{other_doc.document_id}", expected_status=404)
    assert "无权访问" in cross_detail.text or "不存在" in cross_detail.text


@pytest.mark.release
def test_g4_document_update_append_and_delete_reject_cross_tenant_access(
    tenant_admin_api: ReleaseApiClient,
    tenant_admin_api_b: ReleaseApiClient,
    tenant_a: TenantSeed,
    make_release_document,
) -> None:
    own_doc = make_release_document(
        client=tenant_admin_api,
        tenant=tenant_a,
        file_name=f"pytest-g4-own-{int(time.time())}.pdf",
        content=_sample_pdf_bytes("pytest g4 own document"),
        content_type="application/pdf",
    )

    update_response = tenant_admin_api.put(
        f"/api/documents/{own_doc.document_id}",
        json={"remark": "pytest g4 own update"},
        expected_status=200,
    )
    update_data = ReleaseApiClient.json_data(update_response)
    assert int(update_data["documentId"]) == own_doc.document_id

    append_response = tenant_admin_api.post(
        f"/api/documents/{own_doc.document_id}/attachments",
        data={"mergeMode": "new", "remark": "pytest attachment"},
        files=[("files", ("attachment.pdf", _sample_pdf_bytes("pytest attachment"), "application/pdf"))],
        expected_status=200,
    )
    append_data = ReleaseApiClient.json_data(append_response)
    new_document_id = int(append_data["documentId"])
    assert new_document_id != own_doc.document_id
    assert str(append_data.get("tenantCode") or "") == tenant_a.tenant_code
    assert int(append_data.get("previousVersionId") or 0) == own_doc.document_id

    cross_update = tenant_admin_api_b.put(
        f"/api/documents/{new_document_id}",
        json={"remark": "should fail"},
        expected_status=404,
    )
    assert "无权访问" in cross_update.text or "不存在" in cross_update.text

    cross_append = tenant_admin_api_b.post(
        f"/api/documents/{new_document_id}/attachments",
        data={"mergeMode": "new", "remark": "should fail"},
        files=[("files", ("cross.pdf", _sample_pdf_bytes("cross tenant"), "application/pdf"))],
        expected_status=404,
    )
    assert "无权访问" in cross_append.text or "不存在" in cross_append.text

    cross_delete = tenant_admin_api_b.delete(f"/api/documents/{new_document_id}", expected_status=404)
    assert "无权访问" in cross_delete.text or "不存在" in cross_delete.text


@pytest.mark.release
def test_g4_common_user_only_sees_self_created_documents(
    common_api_a: ReleaseApiClient,
    tenant_admin_api: ReleaseApiClient,
    tenant_a: TenantSeed,
    make_release_document,
) -> None:
    user_doc = make_release_document(
        client=common_api_a,
        tenant=tenant_a,
        file_name=f"pytest-g4-common-self-{int(time.time())}.txt",
    )
    admin_doc = make_release_document(
        client=tenant_admin_api,
        tenant=tenant_a,
        file_name=f"pytest-g4-common-other-{int(time.time())}.txt",
    )

    own_list = ReleaseApiClient.json_data(common_api_a.get("/api/documents/list?page=1&pageSize=100"))
    own_ids = _document_ids(own_list["documents"])
    assert user_doc.document_id in own_ids
    assert admin_doc.document_id not in own_ids

    own_detail = ReleaseApiClient.json_data(common_api_a.get(f"/api/documents/{user_doc.document_id}"))
    assert int(own_detail["documentId"]) == user_doc.document_id

    hidden_detail = common_api_a.get(f"/api/documents/{admin_doc.document_id}", expected_status=404)
    assert "无权访问" in hidden_detail.text or "不存在" in hidden_detail.text


@pytest.mark.release
def test_g4_govdoc_list_endpoint_does_not_fail_when_backfilling_version_groups(
    tenant_admin_api: ReleaseApiClient,
) -> None:
    response = tenant_admin_api.get("/api/govdoc/documents?page=1&pageSize=10", expected_status=200)
    payload = response.json()
    assert payload.get("code") in {0, 200}, payload
    assert "data" in payload, payload
