"""Knowledge base API: CRUD, upload/ingest, search, deletion, RBAC, tenancy."""

from __future__ import annotations

from legate.policy.roles import Role

POLICY = (
    b"Our refund policy lets customers request a refund within 30 days. "
    b"Refunds go back to the original payment method within five business days."
)


def test_upload_ingests_and_search_returns_citations(client, helpers):
    owner = helpers.bootstrap_owner(client)
    token = owner["access_token"]
    kb = helpers.create_kb(client, token, name="Support KB")

    doc = helpers.upload_document(client, token, kb["id"], filename="policy.txt", content=POLICY)
    assert doc["status"] == "ready"  # inline ingestion in tests
    assert doc["chunk_count"] >= 1

    docs = client.get(f"/knowledge-bases/{kb['id']}/documents", headers=helpers.headers(token))
    assert len(docs.json()) == 1

    search = client.post(
        f"/knowledge-bases/{kb['id']}/search",
        json={"query": "how long do refunds take", "top_k": 3},
        headers=helpers.headers(token),
    )
    assert search.status_code == 200
    results = search.json()["results"]
    assert results
    assert "refund" in results[0]["text"].lower()
    assert results[0]["document_id"] == doc["id"]
    assert results[0]["source"] == "policy.txt"


def test_delete_document_removes_its_vectors(client, helpers):
    owner = helpers.bootstrap_owner(client)
    token = owner["access_token"]
    kb = helpers.create_kb(client, token)
    doc = helpers.upload_document(client, token, kb["id"], content=POLICY)

    before = client.post(
        f"/knowledge-bases/{kb['id']}/search",
        json={"query": "refund"},
        headers=helpers.headers(token),
    ).json()
    assert before["results"]

    deleted = client.delete(f"/documents/{doc['id']}", headers=helpers.headers(token))
    assert deleted.status_code == 204

    after = client.post(
        f"/knowledge-bases/{kb['id']}/search",
        json={"query": "refund"},
        headers=helpers.headers(token),
    ).json()
    assert after["results"] == []


def test_unsupported_file_type_rejected(client, helpers):
    owner = helpers.bootstrap_owner(client)
    token = owner["access_token"]
    kb = helpers.create_kb(client, token)
    resp = client.post(
        f"/knowledge-bases/{kb['id']}/documents",
        files={"file": ("data.bin", b"\x00\x01", "application/octet-stream")},
        headers=helpers.headers(token),
    )
    assert resp.status_code == 422


def test_reingest_endpoint(client, helpers):
    owner = helpers.bootstrap_owner(client)
    token = owner["access_token"]
    kb = helpers.create_kb(client, token)
    doc = helpers.upload_document(client, token, kb["id"], content=POLICY)

    resp = client.post(f"/documents/{doc['id']}/reingest", headers=helpers.headers(token))
    assert resp.status_code == 200
    assert resp.json()["status"] == "ready"


def test_rbac_builder_can_manage_viewer_cannot(client, helpers):
    owner = helpers.bootstrap_owner(client)
    builder = helpers.add_member(client, owner["access_token"], email="b@x.com", role=Role.BUILDER)
    viewer = helpers.add_member(client, owner["access_token"], email="v@x.com", role=Role.VIEWER)

    kb = helpers.create_kb(client, builder["access_token"])  # builder can create

    forbidden = client.post(
        "/knowledge-bases", json={"name": "Nope"}, headers=helpers.headers(viewer["access_token"])
    )
    assert forbidden.status_code == 403

    upload_forbidden = client.post(
        f"/knowledge-bases/{kb['id']}/documents",
        files={"file": ("p.txt", POLICY, "text/plain")},
        headers=helpers.headers(viewer["access_token"]),
    )
    assert upload_forbidden.status_code == 403

    # Viewer can still read/search.
    assert (
        client.get("/knowledge-bases", headers=helpers.headers(viewer["access_token"])).status_code
        == 200
    )


def test_knowledge_bases_are_tenant_scoped(client, helpers):
    a = helpers.bootstrap_owner(client, email="a@x.com", name="A")
    b = helpers.bootstrap_owner(client, email="b@x.com", name="B")
    kb = helpers.create_kb(client, a["access_token"], name="Secret")

    assert (
        client.get(
            f"/knowledge-bases/{kb['id']}", headers=helpers.headers(b["access_token"])
        ).status_code
        == 404
    )
    assert client.get("/knowledge-bases", headers=helpers.headers(b["access_token"])).json() == []
