import unittest
from time import sleep

from django.conf import settings
from django.core.management import call_command
from django.test import TestCase
from django.urls import reverse

from oscar.core.loading import get_class, get_model

Product = get_model("catalogue", "Product")
update_index_products = get_class("search.helpers", "update_index_products")


class ElasticSearchViewTest(TestCase):
    fixtures = [
        "search/auth",
        "search/catalogue",
    ]

    @classmethod
    def setUpClass(cls):
        # clear search index
        try:
            call_command("update_oscar_index")
        except Exception as exc:  # pragma: no cover
            raise unittest.SkipTest(
                f"Elasticsearch is unavailable for test setup: {exc}"
            ) from exc
        super().setUpClass()

    def setUp(self):
        super().setUp()
        update_index_products(Product.objects.values_list("id", flat=True))
        sleep(3)

    def test_search_bikini(self):
        url = reverse("search:search")
        response = self.client.get("%s?q=bikini" % url)
        self.assertContains(response, "Hermes Bikini")

    def test_search_suggestion(self):
        url = reverse("search:search")
        response = self.client.get("%s?q=prods" % url)
        self.assertEqual(response.context["suggestion"], "produ")

    def test_opensearchdescription(self):
        url = reverse("search:opensearchdescription")
        response = self.client.get(url)
        self.assertContains(response, "application/opensearchdescription+xml")

    def test_opensearchdescription_search(self):
        url = reverse("search:opensearch-autocomplete")
        response = self.client.get("%s?q=h" % url)
        self.assertEqual(response.json(), ["h", ["Hermes Bikini", "Hubble Photo"]])

    def test_opensearchdescription_crappy_browser(self):
        url = reverse("search:opensearch-autocomplete")
        response = self.client.get("%s?searchTerms={{searchTerms}}" % url)
        self.assertEqual(response.json(), [None, []])

    def test_browse(self):
        url = reverse("catalogue:index")
        response = self.client.get(url)
        self.assertContains(response, "second")
        self.assertContains(response, "serious product")
        self.assertContains(response, "Hubble Photo")
        self.assertContains(response, "Hermes Bikini")

    def test_catagory(self):
        url = reverse("catalogue:category", args=("root", 1))
        response = self.client.get(url)
        self.assertContains(response, "second")
        self.assertContains(response, "serious product")
        self.assertContains(response, "Hubble Photo")
        self.assertContains(response, "Hermes Bikini")

    def test_no_stockrecord_and_not_public(self):
        self.test_catagory()

        hermes = Product.objects.get(pk=2)
        hermes.stockrecords.all().delete()
        hermes.save()

        hubble = Product.objects.get(pk=3)
        hubble.is_public = False
        hubble.save()

        update_index_products([hermes.pk, hubble.pk])
        sleep(2)

        url = reverse("catalogue:category", args=("root", 1))
        response = self.client.get(url)
        self.assertContains(response, "second")
        self.assertContains(response, "serious product")
        self.assertNotContains(response, "Hubble Photo")
        self.assertNotContains(response, "Hermes Bikini")


class OldSettingsTest(TestCase):
    def test_autocomplete_filter(self):
        if hasattr(settings, "OSCAR_ELASTICSEARCH_SUGGESTION_STATUS_FILTER"):
            self.fail(
                "OSCAR_ELASTICSEARCH_SUGGESTION_STATUS_FILTER is outdated, please use OSCAR_ELASTICSEARCH_AUTOCOMPLETE_STATUS_FILTER"
            )
