"""Shared test fixtures for Phase 2."""

from __future__ import annotations

import pytest

from simorgh.apps.accounts.models import User
from simorgh.apps.iam.models import Permission, Role
from simorgh.apps.iam.registry import sync_registry_to_db
from simorgh.apps.memberships.models import Membership
from simorgh.apps.organizations.services import create_node
from simorgh.apps.tenants.models import Tenant


@pytest.fixture
def perms(db) -> dict[str, Permission]:
    sync_registry_to_db()
    return {p.codename: p for p in Permission.objects.all()}


@pytest.fixture
def tenant_acme(db) -> Tenant:
    return Tenant.objects.create(slug="acme", name="Acme")


@pytest.fixture
def tenant_globex(db) -> Tenant:
    return Tenant.objects.create(slug="globex", name="Globex")


@pytest.fixture
def acme_tree(tenant_acme):
    root = create_node(tenant_id=tenant_acme.pk, name="HQ")
    eu = create_node(tenant_id=tenant_acme.pk, name="EU", parent=root)
    de = create_node(tenant_id=tenant_acme.pk, name="DE", parent=eu)
    us = create_node(tenant_id=tenant_acme.pk, name="US", parent=root)
    return {"root": root, "eu": eu, "de": de, "us": us}


@pytest.fixture
def role_admin(tenant_acme, perms) -> Role:
    role = Role.objects.create(tenant=tenant_acme, code="admin", name="Admin")
    role.permissions.set(perms.values())
    return role


@pytest.fixture
def role_viewer(tenant_acme, perms) -> Role:
    role = Role.objects.create(tenant=tenant_acme, code="viewer", name="Viewer")
    role.permissions.set([perms["tenants.tenant.view"], perms["organizations.node.view"]])
    return role


@pytest.fixture
def alice(db) -> User:
    return User.objects.create_user("+989000000001", password="x", email="alice@example.com")


@pytest.fixture
def alice_membership(alice, tenant_acme, acme_tree, role_viewer) -> Membership:
    m = Membership.objects.create(
        tenant=tenant_acme,
        organization_node=acme_tree["eu"],
        role=role_viewer,
    )
    m.users.add(alice)
    return m
