import datetime

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

from la_chariotte.order.models import GroupedOrder, Item

from .utils import create_grouped_order

pytestmark = pytest.mark.django_db


class TestGroupedOrderModel:
    """Tests for Grouped orders model"""

    def test_is_open_with_ongoing_grouped_order(self):
        deadline = timezone.now() + datetime.timedelta(days=10)
        ongoing_gr_order = GroupedOrder(deadline=deadline)
        assert ongoing_gr_order.is_open()

    def test_is_open_with_old_grouped_order(self):
        deadline = timezone.now() - datetime.timedelta(hours=1)
        old_gr_order = GroupedOrder(deadline=deadline)
        assert not old_gr_order.is_open()

    def test_is_to_be_delivered_with_today_delivery(self):
        del_date = timezone.now().date()
        gr_order = GroupedOrder(delivery_date=del_date)
        assert gr_order.is_to_be_delivered()

    def test_is_to_be_delivered_with_old_grouped_order(self):
        del_date = timezone.now().date() - datetime.timedelta(days=1)
        old_gr_order = GroupedOrder(delivery_date=del_date)
        assert not old_gr_order.is_to_be_delivered()

    def test_is_to_be_delivered_with_crossed_deadline_grouped_order(self):
        deadline = timezone.now() - datetime.timedelta(hours=1)
        del_date = timezone.now().date() + datetime.timedelta(days=1)
        old_gr_order = GroupedOrder(deadline=deadline, delivery_date=del_date)
        assert old_gr_order.is_to_be_delivered()

    def test_deadline_after_delivery_date_returns_an_error(self, client_log):
        assert GroupedOrder.objects.count() == 0
        create_gorder_url = reverse("order:create_grouped_order")
        response = client_log.get(create_gorder_url)
        assert response.status_code == 200
        date = timezone.now().date() + datetime.timedelta(days=22)
        deadline = timezone.now() + datetime.timedelta(days=32)
        response = client_log.post(
            create_gorder_url,
            {
                "name": "titre test",
                "deadline_date": deadline.date(),
                "deadline_time": deadline.time().strftime("%H:%M"),
                "delivery_date": date,
            },
        )
        assert response.status_code == 200
        assert not response.context.get("form").is_valid()
        assert (
            response.context.get("form").errors["__all__"][0]
            == "La date limite de commande doit être avant la date de livraison"
        )
        assert GroupedOrder.objects.count() == 0

    def test_deadline_same_day_as_delivery_date_does_not_raise(self, client_log):
        assert GroupedOrder.objects.count() == 0
        create_gorder_url = reverse("order:create_grouped_order")
        response = client_log.get(create_gorder_url)
        assert response.status_code == 200
        date = timezone.now().date() + datetime.timedelta(days=32)
        deadline = timezone.now() + datetime.timedelta(days=32)
        response = client_log.post(
            create_gorder_url,
            {
                "name": "titre test",
                "deadline_date": deadline.date(),
                "deadline_time": deadline.time().strftime("%H:%M"),
                "delivery_date": date,
            },
        )
        assert response.status_code == 302
        assert GroupedOrder.objects.count() == 1

    def test_delivery_date_in_past_raise_error(self, client_log):
        assert GroupedOrder.objects.count() == 0
        create_gorder_url = reverse("order:create_grouped_order")
        response = client_log.get(create_gorder_url)
        assert response.status_code == 200
        date = timezone.now().date() - datetime.timedelta(days=1)
        deadline = timezone.now() - datetime.timedelta(days=3)
        response = client_log.post(
            create_gorder_url,
            {
                "name": "titre test",
                "deadline_date": deadline.date(),
                "deadline_time": deadline.time().strftime("%H:%M"),
                "delivery_date": date,
            },
        )
        assert response.status_code == 200
        assert not response.context.get("form").is_valid()
        assert (
            response.context.get("form").errors["__all__"][0]
            == "La date de livraison ne doit pas être dans le passé"
        )
        "La date de livraison ne doit pas être dans le passé" in response.content.decode()
        assert GroupedOrder.objects.count() == 0

    def test_create_unique_code_from_pk(self, client_log):
        grouped_order = create_grouped_order(
            days_before_delivery_date=5,
            days_before_deadline=2,
            name="future",
            orga_user=auth.get_user(client_log),
        )
        assert len(grouped_order.code) == 6


class TestItemModel:
    def test_items_are_sorted_by_name(self, client_log):
        date = timezone.now() + datetime.timedelta(days=3)
        grouped_order = GroupedOrder.objects.create(
            name="test",
            orga=auth.get_user(client_log),
            delivery_date=date.date(),
            deadline=date,
        )
        item = Item.objects.create(
            name="atest item 1", grouped_order=grouped_order, price=1, max_limit=20
        )
        item2 = Item.objects.create(
            name="ctest item 2", grouped_order=grouped_order, price=5
        )
        item3 = Item.objects.create(
            name="btest item 3", grouped_order=grouped_order, price=5
        )
        assert grouped_order.item_set.first() == item
        assert grouped_order.item_set.all()[1] == item3
        assert grouped_order.item_set.all()[2] == item2
