from unittest import mock

from django.core.cache import cache
from django.test import TestCase, override_settings
from lxml import etree

from ocyan.main.loading import get_ocyan_class

gather_sitemaps = get_ocyan_class(
    "wagtail_oscar_integration.sitemap", "gather_sitemaps"
)


def select_urls(response):
    parsed_response = etree.fromstring(response.content)
    ns = {"sitemap": "http://www.sitemaps.org/schemas/sitemap/0.9"}
    return parsed_response.xpath("//sitemap:loc/text()", namespaces=ns)


@override_settings(
    CACHES={"default": {"BACKEND": "django.core.cache.backends.dummy.DummyCache"}}
)
class ProductsSitemapTest(TestCase):
    fixtures = [
        "wagtail_oscar_integration/catalogue",
        "wagtail_oscar_integration/sites",
    ]

    def setUp(self):
        cache.clear()
        super().setUp()

    def assertNoDuplicates(self, iterable, message=None):
        return self.assertEqual(len(set(iterable)), len(iterable), message)

    def test_no_duplicates(self):
        product_sitemap = gather_sitemaps()["products"]
        product_ids = [p.pk for p in product_sitemap().items()]
        self.assertNoDuplicates(
            product_ids, "there are no duplicate items in the product sitemap"
        )

    @mock.patch(
        "ocyan.plugin.wagtail_oscar_integration.sitemap.INCLUDE_CHILD_PRODUCTS_IN_SITEMAP",
        False,
    )
    def test_product_sitemap_browsable(self):
        response = self.client.get("/sitemap-products.xml?zult=gll")
        urls = select_urls(response)

        self.assertNoDuplicates(urls, "There should be no duplicates in the sitemap")
        self.assertListEqual(
            sorted(urls),
            [
                "http://testserver/dikke-shit-ouwe-2/",
                "http://testserver/henk-3/",
                "http://testserver/klats-6/",
                "http://testserver/second-5/",
                "http://testserver/serious-product-4/",
            ],
        )

    @mock.patch(
        "ocyan.plugin.wagtail_oscar_integration.sitemap.INCLUDE_CHILD_PRODUCTS_IN_SITEMAP",
        True,
    )
    def test_product_sitemap_include_childs(self):
        response = self.client.get("/sitemap-products.xml")
        urls = select_urls(response)

        self.assertNoDuplicates(
            urls,
            "There should be no duplicates in the sitemap, even when including children",
        )
        self.assertListEqual(
            sorted(urls),
            [
                "http://testserver/dikke-shit-ouwe-2/",
                "http://testserver/harrie-7/",
                "http://testserver/henk-3/",
                "http://testserver/klats-6/",
                "http://testserver/second-5/",
                "http://testserver/secondchild-8/",
                "http://testserver/serious-product-4/",
            ],
        )


@override_settings(
    CACHES={"default": {"BACKEND": "django.core.cache.backends.dummy.DummyCache"}}
)
class CategorySitemapTest(TestCase):
    fixtures = [
        "wagtail_oscar_integration/catalogue",
        "wagtail_oscar_integration/sites",
    ]

    def test_category_sitemap(self):
        response = self.client.get("/sitemap-categories.xml")
        urls = select_urls(response)
        self.assertListEqual(
            urls,
            [
                "http://testserver/categorie/root-1/",
                "http://testserver/categorie/grav-equip-3/",
            ],
        )


@override_settings(
    CACHES={"default": {"BACKEND": "django.core.cache.backends.dummy.DummyCache"}}
)
class PagesSitemapTest(TestCase):
    fixtures = ["wagtail_oscar_integration/pages", "wagtail_oscar_integration/sites"]

    def test_page_sitemap(self):
        response = self.client.get("/sitemap-pages.xml")

        self.assertEqual(
            response.content,
            b'<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">\n<url><loc>http://testserver/</loc></url>\n</urlset>\n',
        )


@override_settings(
    CACHES={"default": {"BACKEND": "django.core.cache.backends.dummy.DummyCache"}}
)
class ShopSitemapTest(TestCase):
    fixtures = ["wagtail_oscar_integration/sites"]

    def test_shop_sitemap_oxyan(self):
        response = self.client.get("/sitemap-shop.xml?oxyan")

        self.assertEqual(
            response.content,
            b'<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">\n<url><loc>http://testserver/offers/</loc></url>\n</urlset>\n',
        )
