from django.contrib.auth.models import Permission
from django.test import TestCase, Client
from django.urls import reverse
from .test_requests import RequestFixture, setup_requests
from .models import PartsRequest, StockReservation


class RequestAdminTests(RequestFixture, TestCase):
    @classmethod
    def setUpTestData(cls):
        setup_requests(cls)
        cls.engineer.is_staff = True
        cls.engineer.save()
        cls.engineer.user_permissions.set(Permission.objects.filter(content_type__app_label="inventory"))

    def setUp(self):
        self.client.force_login(self.actor)

    def test_create_request_with_inline_through_service(self):
        self.client.force_login(self.engineer)
        url = reverse("admin:inventory_partsrequest_add")
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        response = self.client.post(url, {"service_case": str(self.case.pk), "note": "Admin request", "_save": "Save",
            "lines-TOTAL_FORMS": "1", "lines-INITIAL_FORMS": "0", "lines-MIN_NUM_FORMS": "0", "lines-MAX_NUM_FORMS": "1000",
            "lines-0-spare_part": str(self.part.pk), "lines-0-quantity": "2"})
        self.assertEqual(response.status_code, 302)
        self.assertEqual(PartsRequest.objects.get().lines.get().quantity, 2)

    def test_signed_approval_action(self):
        row = self.request()
        url = reverse("admin:inventory_partsrequest_changelist")
        data = {"action": "approve_selected", "_selected_action": str(row.pk)}
        response = self.client.post(url, data)
        self.assertEqual(response.status_code, 200)
        self.client.post(url, data | {"confirm_transition": "1", "transition_revision": response.context_data["transition_revision"]})
        row.refresh_from_db()
        self.assertEqual(row.status, "APPROVED")

    def test_stale_approval_rejected(self):
        row = self.request()
        url = reverse("admin:inventory_partsrequest_changelist")
        data = {"action": "approve_selected", "_selected_action": str(row.pk)}
        response = self.client.post(url, data)
        self.approve(row)
        self.client.post(url, data | {"confirm_transition": "1", "transition_revision": response.context_data["transition_revision"]})
        self.assertEqual(row.events.count(), 2)

    def test_request_direct_edit_and_delete_rejected(self):
        row = self.request()
        self.assertEqual(self.client.post(reverse("admin:inventory_partsrequest_change", args=[row.pk]), {"status": "APPROVED"}).status_code, 403)
        self.assertEqual(self.client.post(reverse("admin:inventory_partsrequest_delete", args=[row.pk]), {"post": "yes"}).status_code, 403)

    def test_reservation_add_uses_signed_request_revision(self):
        self.receive()
        row = self.approve(self.request())
        url = reverse("admin:inventory_stockreservation_add")
        response = self.client.get(url)
        token = response.context["adminform"].form.initial["request_revisions"]
        response = self.client.post(url, {"line": str(row.lines.get().pk), "location": str(self.location.pk), "quantity": "1", "request_revisions": token, "_save": "Save"})
        self.assertEqual(response.status_code, 302)
        self.assertEqual(StockReservation.objects.get().status, "ACTIVE")

    def test_reservation_stale_form_rejected(self):
        self.receive()
        row = self.approve(self.request())
        url = reverse("admin:inventory_stockreservation_add")
        response = self.client.get(url)
        token = response.context["adminform"].form.initial["request_revisions"]
        self.reserve(row)
        self.client.post(url, {"line": str(row.lines.get().pk), "location": str(self.location.pk), "quantity": "1", "request_revisions": token, "_save": "Save"})
        self.assertEqual(StockReservation.objects.count(), 1)

    def test_release_confirmation_and_readonly_history(self):
        self.receive()
        row = self.reserve(self.approve(self.request()))
        url = reverse("admin:inventory_stockreservation_changelist")
        data = {"action": "release_selected", "_selected_action": str(row.pk)}
        response = self.client.post(url, data)
        self.client.post(url, data | {"confirm_transition": "1", "transition_revision": response.context_data["transition_revision"], "reason": "Unused"})
        row.refresh_from_db()
        self.assertEqual(row.status, "RELEASED")
        self.assertEqual(self.client.post(reverse("admin:inventory_stockreservation_change", args=[row.pk]), {"quantity": "99"}).status_code, 403)

    def test_csrf_required(self):
        client = Client(enforce_csrf_checks=True)
        client.force_login(self.actor)
        self.assertEqual(client.post(reverse("admin:inventory_partsrequest_changelist"), {"action": "approve_selected"}).status_code, 403)
