from django.contrib.auth import get_user_model
from django.test import TestCase
from rest_framework.exceptions import PermissionDenied
from rest_framework.test import APIRequestFactory

from account.permissions import (
    accessible_shops,
    accessible_warehouses,
    assert_shop_access,
    assert_warehouse_access,
)
from shop_management.models.data.organization import Warehouse
from shop_management.models.data.shop import Shop
from shop_management.serializers.data.organization import WarehouseSerializer


class BranchWarehouseIsolationTests(TestCase):
    def setUp(self):
        User = get_user_model()
        self.owner = User.objects.create_user(username="owner", password="x", is_staff=True)
        self.staff = User.objects.create_user(username="staff", password="x", is_staff=True)
        self.other = User.objects.create_user(username="other", password="x", is_staff=True)
        self.kabul = Shop.objects.create(name="Kabul", owner=self.owner)
        self.herat = Shop.objects.create(name="Herat", owner=self.other)
        self.kabul.assigned_users.add(self.staff)
        self.kabul_warehouse = Warehouse.objects.create(shop=self.kabul, code="KBL", name="Kabul Main")
        self.herat_warehouse = Warehouse.objects.create(shop=self.herat, code="HRT", name="Herat Main")
        self.factory = APIRequestFactory()

    def request_for(self, shop):
        request = self.factory.get("/", HTTP_X_SELECTED_SHOP=str(shop.pk))
        request.user = self.staff
        return request

    def test_accessible_queries_only_return_assigned_branch(self):
        request = self.request_for(self.kabul)
        self.assertEqual(list(accessible_shops(self.staff, request)), [self.kabul])
        self.assertEqual(list(accessible_warehouses(self.staff, request)), [self.kabul_warehouse])

    def test_forged_branch_and_warehouse_ids_are_rejected(self):
        request = self.request_for(self.kabul)
        with self.assertRaises(PermissionDenied):
            assert_shop_access(self.staff, self.herat, request)
        with self.assertRaises(PermissionDenied):
            assert_warehouse_access(self.staff, self.herat_warehouse, request)

    def test_selected_branch_blocks_another_assigned_branch(self):
        self.herat.assigned_users.add(self.staff)
        request = self.request_for(self.kabul)
        with self.assertRaises(PermissionDenied):
            assert_warehouse_access(self.staff, self.herat_warehouse, request)

    def test_warehouse_serializer_uses_central_access_rule(self):
        request = self.request_for(self.kabul)
        serializer = WarehouseSerializer(
            data={"shop": self.herat.pk, "code": "BAD", "name": "Forbidden"},
            context={"request": request},
        )
        with self.assertRaises(PermissionDenied):
            serializer.is_valid(raise_exception=True)
