import shutil
import tempfile

from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.test import override_settings
from rest_framework.test import APITestCase

from apps.boletas.models import Boleta
from apps.boletas.utils import build_folio
from apps.catalogos.models import Contrato, ContratoVariedad, Oficina, Productor, Variedad, Zafra
from apps.expediente.models import Disputa
from apps.recepciones.models import Muestreo, PesoRecepcion, Recepcion


User = get_user_model()


TEMP_MEDIA_ROOT = tempfile.mkdtemp()


@override_settings(MEDIA_ROOT=TEMP_MEDIA_ROOT)
class ExpedienteTests(APITestCase):
    @classmethod
    def tearDownClass(cls):
        super().tearDownClass()
        shutil.rmtree(TEMP_MEDIA_ROOT, ignore_errors=True)

    def setUp(self):
        self.user = User.objects.create_user(
            username="user",
            email="user@example.com",
            password="user12345",
        )

        self.office = Oficina.objects.create(codigo="OF-1", nombre="Oficina 1", created_by=self.user, updated_by=self.user)
        self.user.profile.oficinas.add(self.office)

        self.zafra = Zafra.objects.create(nombre="Z 2026", fecha_inicio="2026-01-01", fecha_fin="2026-12-31", created_by=self.user, updated_by=self.user)
        self.variedad = Variedad.objects.create(nombre="V1", created_by=self.user, updated_by=self.user)
        self.productor = Productor.objects.create(
            nombre="Prod 1",
            rfc="ABC123456T12",
            created_by=self.user,
            updated_by=self.user,
        )
        self.contrato = Contrato.objects.create(
            numero_contrato="C-1",
            productor=self.productor,
            zafra=self.zafra,
            activo=True,
            created_by=self.user,
            updated_by=self.user,
        )
        ContratoVariedad.objects.create(
            contrato=self.contrato,
            variedad=self.variedad,
            created_by=self.user,
            updated_by=self.user,
        )

        self.boleta_folio = build_folio(self.office.codigo, self.productor.id, self.zafra.fecha_inicio.year, 1)
        self.boleta = Boleta.objects.create(
            zafra=self.zafra,
            oficina=self.office,
            productor=self.productor,
            contrato=self.contrato,
            folio=self.boleta_folio,
            qr_texto=f"zafra:{self.zafra.id}|folio:{self.boleta_folio}",
            created_by=self.user,
            updated_by=self.user,
        )

        self.recepcion = Recepcion.objects.create(
            boleta=self.boleta,
            oficina=self.office,
            estado=Recepcion.ESTADO_CERRADA,
            firmas={"firma_receptor": "data:image/png;base64,AAA"},
            created_by=self.user,
            updated_by=self.user,
        )
        PesoRecepcion.objects.create(recepcion=self.recepcion, tipo=PesoRecepcion.TIPO_LLENO, valor="1000.00")
        PesoRecepcion.objects.create(recepcion=self.recepcion, tipo=PesoRecepcion.TIPO_VACIO, valor="800.00")
        self.muestreo = Muestreo.objects.create(recepcion=self.recepcion, oficina=self.office, tipo_muestreo="aleatorio")

        resp = self.client.post(
            "/auth/token/",
            {"username": "user", "password": "user12345"},
            format="json",
        )
        self.token = resp.data["access"]
        self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {self.token}", HTTP_X_OFFICE_ID=str(self.office.id))

    def test_get_expediente(self):
        resp = self.client.get(f"/expediente/boletas/{self.boleta.id}/")
        self.assertEqual(resp.status_code, 200)
        self.assertEqual(resp.data["boleta"]["id"], self.boleta.id)

    def test_pdf_expediente(self):
        resp = self.client.get(f"/expediente/boletas/{self.boleta.id}/pdf/")
        self.assertEqual(resp.status_code, 200)
        self.assertIn("application/pdf", resp["Content-Type"])

    def test_zip_expediente(self):
        resp = self.client.get(f"/expediente/boletas/{self.boleta.id}/zip/")
        self.assertEqual(resp.status_code, 200)
        self.assertIn("application/zip", resp["Content-Type"])

    def test_enviar_erp_requires_permission(self):
        resp = self.client.post(f"/expediente/boletas/{self.boleta.id}/enviar-erp/", {}, format="json")
        self.assertEqual(resp.status_code, 403)

        perm = Permission.objects.get(codename="enviar_erp", content_type__app_label="expediente")
        self.user.user_permissions.add(perm)

        resp2 = self.client.post(f"/expediente/boletas/{self.boleta.id}/enviar-erp/", {}, format="json")
        self.assertEqual(resp2.status_code, 200)
        self.assertTrue(resp2.data["success"])

    def test_reabrir_requires_permission_and_motivo(self):
        resp = self.client.post(f"/expediente/boletas/{self.boleta.id}/reabrir/", {}, format="json")
        self.assertEqual(resp.status_code, 403)

        perm = Permission.objects.get(codename="reabrir_boleta", content_type__app_label="expediente")
        self.user.user_permissions.add(perm)

        resp2 = self.client.post(
            f"/expediente/boletas/{self.boleta.id}/reabrir/",
            {"motivo": "Corrección"},
            format="json",
        )
        self.assertEqual(resp2.status_code, 200)

    def test_crear_disputa(self):
        resp = self.client.post(
            f"/expediente/boletas/{self.boleta.id}/disputas/",
            {"motivo": "No de acuerdo"},
            format="json",
        )
        self.assertEqual(resp.status_code, 201)
        self.assertEqual(Disputa.objects.count(), 1)
