"""Cross-tenant leak prevention via `ScopedQuerySet`."""

from __future__ import annotations

import pytest
from django.db import models

from simorgh.core.context import RequestContext
from simorgh.core.models import TenantScopedModel


# Minimal in-test concrete scoped model bound to the `tests` app label.
class _ScopedThing(TenantScopedModel):
    name = models.CharField(max_length=64)

    class Meta:
        app_label = "tests"


@pytest.fixture(autouse=True, scope="module")
def _create_scoped_thing_table(django_db_setup, django_db_blocker):
    with django_db_blocker.unblock():
        from django.db import connection

        with connection.schema_editor() as editor:
            editor.create_model(_ScopedThing)
    yield
    with django_db_blocker.unblock():
        from django.db import connection

        with connection.schema_editor() as editor:
            editor.delete_model(_ScopedThing)


def _ctx(user, tenant, org_ids):
    return RequestContext(
        actor=user,
        tenant=tenant,
        memberships=(),
        permissions=frozenset(),
        org_node_ids=frozenset(org_ids),
    )


@pytest.mark.django_db
def test_scoped_query_filters_other_tenants(alice, tenant_acme, tenant_globex, acme_tree):
    other_node = type(acme_tree["root"]).objects.create(
        tenant=tenant_globex, name="Globex HQ", path_string="/x/", depth=0
    )
    mine = _ScopedThing.objects.create(
        tenant=tenant_acme, organization_node=acme_tree["eu"], name="mine"
    )
    _ScopedThing.objects.create(tenant=tenant_globex, organization_node=other_node, name="not mine")

    ctx = _ctx(alice, tenant_acme, {acme_tree["eu"].pk})
    visible = list(_ScopedThing.objects.scoped_for(ctx).values_list("name", flat=True))
    assert visible == ["mine"]
    assert _ScopedThing.objects.scoped_for(ctx).count() == 1
    assert _ScopedThing.objects.scoped_for(ctx).first().pk == mine.pk


@pytest.mark.django_db
def test_unauthenticated_context_yields_empty(tenant_acme):
    ctx = _ctx(None, tenant_acme, set())
    assert _ScopedThing.objects.scoped_for(ctx).count() == 0


@pytest.mark.django_db
def test_no_org_ids_yields_empty_even_with_tenant(alice, tenant_acme):
    ctx = _ctx(alice, tenant_acme, set())
    assert _ScopedThing.objects.scoped_for(ctx).count() == 0
