from kinto.core.testing import unittest

from .support import MINIMALIST_BUCKET, MINIMALIST_COLLECTION, MINIMALIST_RECORD, BaseWebTest


class GlobalSettingsTest(BaseWebTest, unittest.TestCase):
    @classmethod
    def get_app_settings(cls, extras=None):
        settings = super().get_app_settings(extras)
        settings["kinto.record_cache_expires_seconds"] = 3600
        settings["kinto.record_read_principals"] = "system.Everyone"
        return settings

    def setUp(self):
        super().setUp()
        self.create_bucket("blog")
        self.app.put_json(
            "/buckets/blog/collections/cached", MINIMALIST_COLLECTION, headers=self.headers
        )
        r = self.app.post_json(
            "/buckets/blog/collections/cached/records", MINIMALIST_RECORD, headers=self.headers
        )
        self.record = r.json["data"]

    def test_expires_and_cache_control_headers_are_set(self):
        url = "/buckets/blog/collections/cached/records"
        r = self.app.get(url)
        self.assertIn("Expires", r.headers)
        self.assertEqual(r.headers["Cache-Control"], "max-age=3600")

        r = self.app.get("{}/{}".format(url, self.record["id"]))
        self.assertIn("Expires", r.headers)
        self.assertEqual(r.headers["Cache-Control"], "max-age=3600")


class SpecificSettingsTest(BaseWebTest, unittest.TestCase):
    @classmethod
    def get_app_settings(cls, extras=None):
        settings = super().get_app_settings(extras)
        settings["kinto.blog.record_cache_expires_seconds"] = "30"
        settings["kinto.browser.top500.record_cache_expires_seconds"] = "60"
        return settings

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

        def create_record_in_collection(bucket_id, collection_id):
            bucket = {**MINIMALIST_BUCKET, "permissions": {"read": ["system.Everyone"]}}
            self.app.put_json("/buckets/{}".format(bucket_id), bucket, headers=self.headers)
            collection_url = "/buckets/{}/collections/{}".format(bucket_id, collection_id)
            self.app.put_json(collection_url, MINIMALIST_COLLECTION, headers=self.headers)
            r = self.app.post_json(
                collection_url + "/records", MINIMALIST_RECORD, headers=self.headers
            )
            return r.json["data"]

        self.blog_record = create_record_in_collection("blog", "cached")
        self.app_record = create_record_in_collection("browser", "top500")

    def assertHasCache(self, url, age):
        r = self.app.get(url)
        self.assertIn("Expires", r.headers)
        self.assertEqual(r.headers["Cache-Control"], "max-age={}".format(age))

    def test_for_records_on_a_specific_bucket(self):
        collection_url = "/buckets/blog/collections/cached/records"
        self.assertHasCache(collection_url, 30)
        record_url = "{}/{}".format(collection_url, self.blog_record["id"])
        self.assertHasCache(record_url, 30)

    def test_for_records_on_a_specific_collection(self):
        collection_url = "/buckets/browser/collections/top500/records"
        self.assertHasCache(collection_url, 60)
        record_url = "{}/{}".format(collection_url, self.app_record["id"])
        self.assertHasCache(record_url, 60)


class CollectionExpiresTest(BaseWebTest, unittest.TestCase):
    def setUp(self):
        super().setUp()
        bucket = {**MINIMALIST_BUCKET, "permissions": {"read": ["system.Everyone"]}}
        self.app.put_json("/buckets/blog", bucket, headers=self.headers)
        self.collection_url = "/buckets/blog/collections/cached"
        self.app.put_json(
            self.collection_url, {"data": {"cache_expires": 3600}}, headers=self.headers
        )

        self.records_url = self.collection_url + "/records"

        resp = self.app.post_json(self.records_url, MINIMALIST_RECORD, headers=self.headers)
        self.record = resp.json["data"]
        self.record_url = "{}/{}".format(self.records_url, self.record["id"])

    def test_cache_expires_must_be_an_integer(self):
        self.app.put_json(
            self.collection_url,
            {"data": {"cache_expires": "abc"}},
            headers=self.headers,
            status=400,
        )

    def test_expires_and_cache_control_are_not_set_if_authenticated(self):
        r = self.app.get(self.records_url, headers=self.headers)
        self.assertNotIn("Expires", r.headers)
        self.assertIn("Cache-Control", r.headers)
        self.assertNotIn("max-age", r.headers["Cache-Control"])

    def test_expires_and_cache_control_are_set_on_records(self):
        r = self.app.get(self.records_url)
        self.assertIn("Expires", r.headers)
        self.assertEqual(r.headers["Cache-Control"], "max-age=3600")

    def test_expires_and_cache_control_are_set_on_record(self):
        r = self.app.get(self.record_url)
        self.assertIn("Expires", r.headers)
        self.assertEqual(r.headers["Cache-Control"], "max-age=3600")

    def test_cache_control_is_set_no_cache_if_zero(self):
        self.app.put_json(
            self.collection_url, {"data": {"cache_expires": 0}}, headers=self.headers
        )
        r = self.app.get(self.records_url)
        self.assertIn("Expires", r.headers)
        self.assertEqual(
            r.headers["Cache-Control"], "max-age=0, must-revalidate, no-cache, no-store"
        )
        self.assertEqual(r.headers["Pragma"], "no-cache")

    def test_cache_control_on_collection_overrides_setting(self):
        app = self.make_app(
            settings={
                "kinto.record_cache_expires_seconds": 10,
                "kinto.record_read_principals": "system.Everyone",
            }
        )
        app.put_json("/buckets/blog", MINIMALIST_BUCKET, headers=self.headers)
        app.put_json(self.collection_url, {"data": {"cache_expires": 3600}}, headers=self.headers)
        r = app.get(self.records_url)
        self.assertIn("Expires", r.headers)
        self.assertEqual(r.headers["Cache-Control"], "max-age=3600")
