from django.contrib import admin
from django.test import TestCase, Client
from django.urls import reverse
from apps.inventory.test_usage import setup_usage
from .tests import QuotationFixture
from .models import ServiceQuotation, QuotationDecision, CommercialWorkAuthorization


class QuotationAdminTests(QuotationFixture,TestCase):
    @classmethod
    def setUpTestData(cls): setup_usage(cls)

    def setUp(self): self.client.force_login(self.actor)

    def url(self,row): return reverse("admin:commercial_quotation_workflow",args=[row.pk])

    def post(self,row,operation,**data):
        response=self.client.get(self.url(row))
        return self.client.post(self.url(row),dict(revision_token=response.context_data["revision_token"],operation=operation)|data)

    def test_admin_creation_delegates(self):
        response=self.client.post(reverse("admin:commercial_servicequotation_add"),dict(service_case=str(self.case.pk),currency="BDT",customer_note="Estimate",internal_note="",valid_until="",_save="Save"))
        self.assertEqual(response.status_code,302)
        self.assertEqual(ServiceQuotation.objects.count(),1)

    def test_get_is_readonly_even_with_operation_query(self):
        row=self.lines(self.create())
        response=self.client.get(self.url(row),dict(operation="submit"))
        self.assertEqual(response.status_code,200)
        row.refresh_from_db()
        self.assertEqual(row.status,"DRAFT")

    def test_submission_decision_revision_workflow(self):
        row=self.lines(self.create())
        self.assertEqual(self.post(row,"submit").status_code,302)
        self.assertEqual(self.post(row,"decision",outcome="APPROVED",channel="EMAIL",recipient_name="Synthetic name",reference="Synthetic approval").status_code,302)
        row.refresh_from_db()
        self.assertEqual(row.status,"APPROVED")
        self.assertEqual(self.post(row,"revise").status_code,302)
        self.assertEqual(ServiceQuotation.objects.count(),2)

    def test_stale_signature_and_tampering(self):
        row=self.create()
        token=self.client.get(self.url(row)).context_data["revision_token"]
        self.lines(row)
        for supplied in (token,"tampered"):
            response=self.client.post(self.url(row),dict(operation="submit",revision_token=supplied))
            self.assertEqual(response.status_code,400)
        row.refresh_from_db()
        self.assertEqual(row.status,"DRAFT")

    def test_csrf_enforced(self):
        row=self.lines(self.create())
        client=Client(enforce_csrf_checks=True)
        client.force_login(self.actor)
        response=client.post(self.url(row),dict(operation="submit"))
        self.assertEqual(response.status_code,403)

    def test_history_delete_disabled(self):
        for model in (ServiceQuotation,QuotationDecision,CommercialWorkAuthorization):
            self.assertFalse(admin.site._registry[model].has_delete_permission(None))

    def test_native_permission_does_not_bypass_business_scope(self):
        from django.contrib.auth.models import Permission
        row=self.create()
        self.user.is_staff=True
        self.user.save()
        self.user.user_permissions.set(Permission.objects.filter(content_type__app_label="commercial"))
        self.client.force_login(self.user)
        response=self.client.get(reverse("admin:commercial_servicequotation_changelist"))
        self.assertNotContains(response,row.family.number)

    def test_historical_notes_are_escaped(self):
        row=self.lines(self.create(customer_note='<script>alert("test")</script>'))
        response=self.client.get(self.url(row))
        self.assertNotContains(response,'<script>alert("test")</script>')
        self.assertContains(response,"&lt;script&gt;")

    def test_draft_metadata_and_line_management_calculate_server_totals(self):
        row=self.create()
        response=self.post(row,"metadata",currency="BDT",customer_note="Reviewed",internal_note="",valid_until="")
        self.assertEqual(response.status_code,302)
        data={"lines-TOTAL_FORMS":"1","lines-INITIAL_FORMS":"0","lines-MIN_NUM_FORMS":"0","lines-MAX_NUM_FORMS":"100",
            "lines-0-kind":"LABOR","lines-0-responsibility":"CUSTOMER","lines-0-description":"Repair labor",
            "lines-0-quantity":"2","lines-0-unit_price":"100.00","lines-0-discount":"10.00","lines-0-tax_rate":"5.00",
            "lines-0-tax_label":"Explicit tax","grand_total":"0"}
        response=self.post(row,"lines",**data)
        self.assertEqual(response.status_code,302)
        row.refresh_from_db()
        self.assertEqual(str(row.grand_total),"199.50")

    def test_signature_is_bound_to_actor(self):
        from django.contrib.auth import get_user_model
        row=self.lines(self.create())
        token=self.client.get(self.url(row)).context_data["revision_token"]
        second=get_user_model().objects.create_superuser(username="other-commercial-admin")
        self.client.force_login(second)
        response=self.client.post(self.url(row),dict(operation="submit",revision_token=token))
        self.assertEqual(response.status_code,400)
