import pytest
from django.contrib import auth
from django.urls import reverse

from la_chariotte.order import models

from .utils import create_grouped_order, order_items_in_grouped_order

pytestmark = pytest.mark.django_db


class TestOrder:
    def test_order_deadline_passed__raise_errors(self, client, other_user):
        """A user orders when the deadline is passed. They get a 403 error"""
        grouped_order = create_grouped_order(
            days_before_delivery_date=5,
            days_before_deadline=-1,
            name="gr order test",
            orga_user=other_user,
        )
        item = models.Item.objects.create(
            name="test item 1", grouped_order=grouped_order, price=2
        )

        # some items are ordered
        order_url = reverse(
            "order:order",
            kwargs={
                "code": grouped_order.code,
            },
        )
        response = client.post(
            order_url,
            {
                f"quantity_{item.pk}": [4, 0],
                "first_name": "Prénom",
                "last_name": "Nom",
                "phone": "0645632569",
                "email": "test@mail.fr",
                "note": "",
            },
        )
        assert response.status_code == 403

    def test_order_deadline_passed__still_works_for_orga(self, client_log):
        """The orga user orders when the deadline is passed, but the delivery is to come. It works"""

        grouped_order = create_grouped_order(
            days_before_delivery_date=5,
            days_before_deadline=-1,
            name="gr order test",
            orga_user=auth.get_user(client_log),
        )
        item = models.Item.objects.create(
            name="test item 1", grouped_order=grouped_order, price=2
        )

        # some items are ordered
        order_url = reverse(
            "order:order",
            kwargs={
                "code": grouped_order.code,
            },
        )
        response = client_log.post(
            order_url,
            {
                f"quantity_{item.pk}": [4, 0],
                "first_name": "Prénom",
                "last_name": "Nom",
                "phone": "0645632569",
                "email": "test@mail.fr",
                "note": "",
            },
        )
        assert response.status_code == 302

    def test_order_delivery_passed__orga(self, client_log):
        """The orga user orders when the deadline and the delivery are passed. The get a 403 error"""

        grouped_order = create_grouped_order(
            days_before_delivery_date=-2,
            days_before_deadline=-4,
            name="gr order test",
            orga_user=auth.get_user(client_log),
        )
        item = models.Item.objects.create(
            name="test item 1", grouped_order=grouped_order, price=2
        )

        # some items are ordered
        order_url = reverse(
            "order:order",
            kwargs={
                "code": grouped_order.code,
            },
        )
        response = client_log.post(
            order_url,
            {
                f"quantity_{item.pk}": [4, 0],
                "first_name": "Prénom",
                "last_name": "Nom",
                "phone": "0645632569",
                "email": "test@mail.fr",
                "note": "",
            },
        )
        assert response.status_code == 403

    def test_order_too_many_items_ordered(self, client, other_user):
        """If a user orderd more articles than what is available,
        the form is displayed again with an error.
        The OrderedItems, OrderAuthor and Order are deleted."""
        grouped_order = create_grouped_order(
            days_before_delivery_date=5,
            days_before_deadline=2,
            name="gr order test",
            orga_user=other_user,
        )
        item = models.Item.objects.create(
            name="test item 1", grouped_order=grouped_order, price=1
        )
        item2 = models.Item.objects.create(
            name="test item 2", grouped_order=grouped_order, price=5, max_limit=20
        )
        detail_url = reverse(
            "order:grouped_order_detail",
            kwargs={
                "code": grouped_order.code,
            },
        )
        response = client.get(detail_url)
        assert response.status_code == 200
        assert "test item" in response.content.decode()
        assert "gr order test" in response.content.decode()
        assert item.ordered_nb == 0
        assert item2.ordered_nb == 0
        order_url = reverse(
            "order:order",
            kwargs={
                "code": grouped_order.code,
            },
        )
        response = client.post(
            order_url,
            {
                f"quantity_{item.pk}": [0, 4],
                f"quantity_{item2.pk}": [0, 25],
                "first_name": "Prénom",
                "last_name": "Nom",
                "phone": "0645632569",
                "email": "test@mail.fr",
                "note": "",
            },
        )
        assert response.status_code == 200
        assert (
            response.context["error_message"]
            == "Trop de test item 2 commandés pour la quantité disponible"
        )
        item.refresh_from_db()
        item2.refresh_from_db()
        assert item.ordered_nb == 0
        assert item2.ordered_nb == 0
        assert not models.OrderAuthor.objects.first()
        assert not models.Order.objects.first()
        assert not models.OrderedItem.objects.first()

    def test_negative_nb_ordered(self, client, other_user):
        """If a user orders a negative nb of articles for an item,
        we consider they ordered 0.
        (but it is also blocked by fronted)"""
        grouped_order = create_grouped_order(
            days_before_delivery_date=5,
            days_before_deadline=2,
            name="gr order test",
            orga_user=other_user,
        )
        item = models.Item.objects.create(
            name="test item 1", grouped_order=grouped_order, price=1
        )
        item2 = models.Item.objects.create(
            name="test item 2", grouped_order=grouped_order, price=5, max_limit=20
        )
        detail_url = reverse(
            "order:grouped_order_detail",
            kwargs={
                "code": grouped_order.code,
            },
        )
        response = client.get(detail_url)
        assert response.status_code == 200
        assert "test item" in response.content.decode()
        assert "gr order test" in response.content.decode()
        assert item.ordered_nb == 0
        assert item2.ordered_nb == 0
        order_url = reverse(
            "order:order",
            kwargs={
                "code": grouped_order.code,
            },
        )
        response = client.post(
            order_url,
            {
                f"quantity_{item.pk}": [4, 0],
                f"quantity_{item2.pk}": [-2, 0],
                "first_name": "Prénom",
                "last_name": "Nom",
                "phone": "0645632569",
                "email": "test@mail.fr",
                "note": "",
            },
        )
        assert response.status_code == 302
        order = models.Order.objects.get(grouped_order=grouped_order.pk)
        assert response.url == reverse(
            "order:order_confirm",
            kwargs={
                "code": grouped_order.code,
                "pk": order.pk,
            },
        )
        item.refresh_from_db()
        item2.refresh_from_db()
        assert models.OrderAuthor.objects.first().first_name == "Prénom"
        assert models.OrderAuthor.objects.first().email == "test@mail.fr"
        assert models.OrderAuthor.objects.first().phone == "0645632569"
        assert item.ordered_nb == 4
        assert item2.ordered_nb == 0
        assert order.ordered_items.count() == 1

    def test_delete_order(self, client_log):
        """The orga user deletes an order. The grouped order is updated"""
        grouped_order = create_grouped_order(
            days_before_delivery_date=5,
            days_before_deadline=2,
            name="gr order test",
            orga_user=auth.get_user(client_log),
        )
        order = order_items_in_grouped_order(grouped_order)
        author = order.author
        order_price = order.price
        item = order.ordered_items.first().item
        assert (
            models.OrderedItem.objects.all().count() == 4
        )  # 4 orderedItem, 2 are in the order 'order'
        assert grouped_order.order_set.all().count() == 3
        assert grouped_order.total_price == 35
        assert item.ordered_nb == 4
        delete_url = reverse(
            "order:order_delete",
            kwargs={"code": grouped_order.code, "pk": order.id},
        )
        response = client_log.post(delete_url)
        assert response.status_code == 302
        assert response.url == reverse(
            "order:grouped_order_overview",
            kwargs={
                "code": grouped_order.code,
            },
        )
        client_log.get(response.url)
        grouped_order.refresh_from_db()
        item.refresh_from_db()
        assert models.OrderedItem.objects.all().count() == 2
        assert grouped_order.order_set.all().count() == 2
        assert grouped_order.total_price == 35 - order_price
        assert item.ordered_nb == 1
