from django.contrib.auth import get_user_model
from rest_framework import status
from rest_framework.test import APITestCase

from checkpoint.models import CheckPoint, FacilityType


User = get_user_model()


class FacilityTypeUpdateTests(APITestCase):
    def setUp(self):
        self.facility_type = FacilityType.objects.create(
            name="Border Point",
            description="Original description",
        )
        self.checkpoint = CheckPoint.objects.create(
            name="Checkpoint One",
            location="Kakarbhitta",
            facility_type=self.facility_type,
        )
        self.admin_user = User.objects.create_user(
            email="facility-admin@example.com",
            password="password123",
            name="Facility Admin",
            role=User.Role.ADMIN,
        )
        self.client.force_authenticate(user=self.admin_user)

    def test_admin_can_partially_update_facility_type(self):
        response = self.client.patch(
            f"/api/v1/facility-types/{self.facility_type.id}/",
            {"description": "Updated description"},
            format="json",
        )

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.facility_type.refresh_from_db()
        self.assertEqual(self.facility_type.description, "Updated description")

    def test_put_update_is_not_exposed(self):
        response = self.client.put(
            f"/api/v1/facility-types/{self.facility_type.id}/",
            {"name": "New name", "description": "New description"},
            format="json",
        )

        self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)

    def test_admin_can_partially_update_checkpoint(self):
        response = self.client.patch(
            f"/api/v1/checkpoints/{self.checkpoint.id}/",
            {"location": "Birgunj"},
            format="json",
        )

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.checkpoint.refresh_from_db()
        self.assertEqual(self.checkpoint.location, "Birgunj")

    def test_checkpoint_put_update_is_not_exposed(self):
        response = self.client.put(
            f"/api/v1/checkpoints/{self.checkpoint.id}/",
            {
                "name": "Checkpoint One",
                "location": "Birgunj",
                "facility_type": str(self.facility_type.id),
            },
            format="json",
        )

        self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)


class CheckPointScopeTests(APITestCase):
    endpoint = "/api/v1/checkpoints/"

    def setUp(self):
        facility_type = FacilityType.objects.create(name="Border Point")
        self.checkpoint_one = CheckPoint.objects.create(
            name="Checkpoint One",
            location="Kakarbhitta",
            facility_type=facility_type,
        )
        self.checkpoint_two = CheckPoint.objects.create(
            name="Checkpoint Two",
            location="Birgunj",
            facility_type=facility_type,
        )

        self.staff_user = User.objects.create_user(
            email="staff@example.com",
            password="password123",
            name="Staff User",
            checkpoint=self.checkpoint_one,
            role=User.Role.STAFF,
        )
        self.admin_user = User.objects.create_user(
            email="admin@example.com",
            password="password123",
            name="Admin User",
            role=User.Role.ADMIN,
        )

    @staticmethod
    def _result_ids(response):
        results = response.data.get("results", response.data)
        return {item["id"] for item in results}

    def test_staff_only_sees_assigned_checkpoint(self):
        self.client.force_authenticate(user=self.staff_user)

        response = self.client.get(self.endpoint)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertSetEqual(self._result_ids(response), {str(self.checkpoint_one.id)})

    def test_admin_sees_all_checkpoints(self):
        self.client.force_authenticate(user=self.admin_user)

        response = self.client.get(self.endpoint)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertSetEqual(
            self._result_ids(response),
            {str(self.checkpoint_one.id), str(self.checkpoint_two.id)},
        )
