# -*- coding: utf-8 -*-
from unittest import mock

from django.conf import settings
from django.contrib.auth import get_user_model
from django.test import TestCase
from django.urls import reverse
from django.utils.translation import gettext

from oscar.core.loading import get_model

import ocyan.core.fender
from ocyan.core.utils import merge_dicts

Basket = get_model("basket", "Basket")
Product = get_model("catalogue", "Product")
User = get_user_model()

ocyan_settings = ocyan.core.fender.config.settings
CHECKOUT_OCYAN_OPTIONS = merge_dicts(
    ocyan_settings, {"shipping": {"enable_charged_shipping": True}}
)


class CheckoutTest(TestCase):
    fixtures = [
        "checkout/auth",
        "checkout/catalogue",
        "checkout/shipping",
        "checkout/sites",
    ]

    def test_catalogue_initialized(self):
        "The catalogue should be initialized"
        self.assertEqual(Product.objects.count(), 2)
        self.assertEqual(User.objects.count(), 2)

    def test_checkout_empty_basket(self):
        "Checkout with empty basket should be disabled"
        if not settings.OSCAR_ALLOW_ANON_CHECKOUT:
            henk = User.objects.get(username="henk")
            self.client.force_login(henk)

        if not settings.SHOW_BASKET_POPUP_MODAL:
            response = self.client.get(reverse("checkout:index"))
            self.assertEqual(
                response.status_code,
                200,
                "The checkout page should work just fine even without a basket",
            )
            self.assertContains(
                response, gettext("Your shopping basket appears to be empty")
            )

    def test_checkout_thank_you_404_or_302(self):
        if not settings.OSCAR_ALLOW_ANON_CHECKOUT:
            henk = User.objects.get(username="henk")
            self.client.force_login(henk)

        response = self.client.get(reverse("checkout:thank-you"))
        self.assertIn(
            response.status_code,
            [404, 302],
            "There should be no thank you page if there is not order",
        )

    @mock.patch("sorl.thumbnail.templatetags.thumbnail.ThumbnailNodeBase.render")
    @mock.patch.object(ocyan.core.fender.config, "settings", CHECKOUT_OCYAN_OPTIONS)
    def test_checkout_with_filled_basket(self, render):
        "The checkout page should work fine with items in the basket"
        render.return_value = ""

        henk = User.objects.get(username="henk")
        self.client.force_login(henk)
        self.assertEqual(Basket.objects.count(), 0, "The basket should be empty")

        basket_add_url = reverse("basket:add", args=(1,))
        body = {"quantity": 3}
        response = self.client.post(basket_add_url, body)
        self.assertEqual(
            response.status_code, 302, "Adding an item to a basket should redirect."
        )

        if not settings.SHOW_BASKET_POPUP_MODAL:
            self.assertEqual(
                response["location"],
                reverse("basket:summary"),
                "Adding item to basket should redirect to basket",
            )

            response = self.client.get(reverse("checkout:index"))
            self.assertEqual(
                response.status_code, 200, "The checkout page should work just fine."
            )
        else:
            success_url = reverse("basket:summary")
            product_pk = 1
            expected_redirect_url = f"{success_url}#prod_{product_pk}"

            self.assertIn(
                expected_redirect_url,
                response["location"],
                "When the basket popup modal is shown, the redirect URL should contain the product reference.",
            )

            self.assertEqual(
                self.client.session.get("added_product"),
                product_pk,
                "The session should store the added product's primary key.",
            )
            self.assertEqual(
                self.client.session.get("added_quantity"),
                str(3),
                "The session should store the correct added quantity.",
            )

    @mock.patch.object(ocyan.core.fender.config, "settings", CHECKOUT_OCYAN_OPTIONS)
    def test_checkout_country_billing_field(self):
        henk = User.objects.get(username="henk")
        self.client.force_login(henk)
        self.assertEqual(Basket.objects.count(), 0, "The basket should be empty")

        basket_add_url = reverse("basket:add", args=(1,))
        body = {"quantity": 3}

        response = self.client.post(basket_add_url, body)
        if not settings.SHOW_BASKET_POPUP_MODAL:
            self.assertEqual(
                response.status_code, 302, "Adding an item to a basket should redirect."
            )
            self.assertEqual(
                response["location"],
                reverse("basket:summary"),
                "Adding item to basket should redirect to basket",
            )
            response = self.client.get(reverse("checkout:index"))
            self.assertEqual(
                response.status_code, 200, "The checkout page should work just fine."
            )
            self.assertContains(
                response, '<div class="form-group id_billing_address_form-country ">'
            )
        else:
            success_url = reverse("basket:summary")
            product_pk = 1
            expected_redirect_url = f"{success_url}#prod_{product_pk}"

            self.assertIn(
                expected_redirect_url,
                response["location"],
                "When the basket popup modal is shown, the redirect URL should contain the product reference.",
            )

            self.assertEqual(
                self.client.session.get("added_product"),
                product_pk,
                "The session should store the added product's primary key.",
            )
            self.assertEqual(
                self.client.session.get("added_quantity"),
                str(3),
                "The session should store the correct added quantity.",
            )
