# (c) cavaliba.com - tests / views / instance_list page reset on new filter

from django.test import TestCase, override_settings
from django.urls import reverse

import app_home.cache as cache
from tests import helper

CLASSNAME = "pagereset"


class TestInstanceListPageResetOnFilter(TestCase):
    def setUp(self):
        cache.clear()
        helper.add_admin_user(login="unittest")
        helper.add_schema(
            classname=CLASSNAME,
            field_definition={
                "mystring": {"dataformat": "string", "displayname": "MyString"},
            },
        )
        helper.add_instance(classname=CLASSNAME, keyname="keep-me", fields={"mystring": "keep-me"})
        helper.add_instance(classname=CLASSNAME, keyname="other", fields={"mystring": "other"})

    def _set_stale_page(self, page=3, size=1):
        # simulate the user having browsed to a later page of the unfiltered
        # list (size=1 so 2 real instances is enough to reach page 3)
        session = self.client.session
        session[CLASSNAME + "_page"] = page
        session[CLASSNAME + "_size"] = size
        session.save()

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_get_query_link_resets_stale_page(self):
        self._set_stale_page(page=3, size=1)

        response = self.client.get(
            reverse("app_data:instance_list", kwargs={"classname": CLASSNAME}),
            {"query": "keep"},
        )

        self.assertEqual(response.status_code, 200)
        # bug: with a stale page=3/size=1, offset=2 skips past the single
        # matching instance entirely -> empty result
        self.assertContains(response, "keep-me")
        self.assertEqual(self.client.session[CLASSNAME + "_page"], 1)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_post_search_resets_stale_page(self):
        self._set_stale_page(page=3, size=1)

        # cv-search-form has action="" - the browser submits it back to the
        # exact current URL, query string included, so a real search POST
        # from page 3 carries "?page=3&size=1" in its own URL. Posting to the
        # bare URL (no query string) doesn't reproduce that and would miss
        # the bug: paginator_for_count() reads request.GET["page"] before
        # the session, so a stale "page=3" in the POST's own URL overrides
        # the session reset unless the view also strips it.
        url = reverse("app_data:instance_list", kwargs={"classname": CLASSNAME})
        response = self.client.post(f"{url}?page=3&size=1", {"query": "keep"})

        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "keep-me")
        self.assertEqual(self.client.session[CLASSNAME + "_page"], 1)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_get_query_link_with_stale_page_param_resets(self):
        # same stale-"page=3"-in-the-URL scenario as the POST case above, but
        # via a GET filter link that (hypothetically) also carries a leftover
        # page param
        self._set_stale_page(page=3, size=1)

        response = self.client.get(
            reverse("app_data:instance_list", kwargs={"classname": CLASSNAME}),
            {"query": "keep", "page": 3, "size": 1},
        )

        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "keep-me")
        self.assertEqual(self.client.session[CLASSNAME + "_page"], 1)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_plain_pagination_link_does_not_reset_page(self):
        self._set_stale_page(page=2, size=1)

        response = self.client.get(
            reverse("app_data:instance_list", kwargs={"classname": CLASSNAME}),
            {"page": 2, "size": 1},
        )

        self.assertEqual(response.status_code, 200)
        # no "query" param -> not a new filter, page must stay as requested
        self.assertEqual(self.client.session[CLASSNAME + "_page"], 2)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_dataview_switch_does_not_reset_page(self):
        self._set_stale_page(page=2, size=1)

        response = self.client.get(
            reverse("app_data:instance_list", kwargs={"classname": CLASSNAME}),
            {"dv": "___ALL___"},
        )

        self.assertEqual(response.status_code, 200)
        # no "query" param -> dataview switch alone must not reset the page
        self.assertEqual(self.client.session[CLASSNAME + "_page"], 2)
