from plone import api
from ploneintranet.imagebank.browser.base import CollectionListingView
from ploneintranet.imagebank.browser.folder import ImageBankFolderUploadForm
from ploneintranet.imagebank.browser.folder import ImageBankFolderView
from ploneintranet.imagebank.browser.menu import ImageBankCollectionMenuView
from ploneintranet.imagebank.browser.panel import CollectionSchemaAdapter
from ploneintranet.imagebank.browser.panel import IPanelCreateCollectionViewSchema
from ploneintranet.imagebank.browser.panel import PanelEditCollectionView
from ploneintranet.imagebank.interfaces import IImageBankFolder
from ploneintranet.imagebank.testing import PLONEINTRANET_IMAGEBANK_INTEGRATION_TESTING

import unittest


class TestImageBankFolder(unittest.TestCase):

    layer = PLONEINTRANET_IMAGEBANK_INTEGRATION_TESTING

    def setUp(self):
        self.portal = self.layer["portal"]
        self.request = self.layer["request"]
        self.app = self.portal.apps["image-bank"]
        self.collections = self.portal["image-bank-collections"]
        with api.env.adopt_user("admin"):
            self.folder = api.content.create(
                container=self.collections,
                type="Folder",
                id="foo",
                title="Foo",
                safe_id=True,
            )

            self.image = api.content.create(
                container=self.folder,
                type="Image",
                id="foo-image",
                title="Foo image",
                safe_id=True,
            )

    def get_view(self, form=None) -> ImageBankFolderView:
        if form is not None:
            self.request.form.update(form)
        view = api.content.get_view(
            "app-image-bank-collection", self.folder, self.request
        )
        return view

    def get_app_view(self, form=None) -> ImageBankFolderView:
        if form is not None:
            self.request.form.update(form)
        view = api.content.get_view("app-image-bank", self.app, self.request)
        return view

    def test_addable_types(self):
        with api.env.adopt_roles(["Contributor"]):
            allowed_types = self.folder.allowedContentTypes()
            allowed_type_ids = {fti.getId() for fti in allowed_types}
            self.assertSetEqual(allowed_type_ids, {"Image"})

    def test_folder_interfaces(self):
        self.assertTrue(IImageBankFolder.providedBy(self.folder))

    def test_folder_view_query(self):
        view = self.get_view()
        self.assertDictEqual(
            view.base_query,
            {
                "context": self.folder,
                "portal_type": "Image",
                "sort_on": "created",
                "sort_order": "descending",
            },
        )
        self.assertDictEqual(
            view.query,
            {
                "context": self.folder,
                "portal_type": "Image",
                "sort_on": "created",
                "sort_order": "descending",
            },
        )

    def test_folder_view_query_with_searchable_text(self):
        view = self.get_view({"SearchableText": "foo"})
        self.assertDictEqual(
            view.base_query,
            {
                "context": self.folder,
                "portal_type": "Image",
                "sort_on": "created",
                "sort_order": "descending",
            },
        )

        self.assertDictEqual(
            view.query,
            {
                "context": self.folder,
                "portal_type": "Image",
                "SearchableText": "foo*",
                "sort_on": "created",
                "sort_order": "descending",
            },
        )

    def test_folder_not_found_if_no_permission(self):
        view = self.get_app_view()
        self.assertNotIn(
            "foo",
            [brain.getId for brain in view.batch],
        )

        with api.env.adopt_roles(["Reviewer"]):
            api.content.transition(obj=self.folder, to_state="published")
        view = self.get_app_view()
        self.assertIn(
            "foo",
            [brain.getId for brain in view.batch],
        )

    def test_listing_view(self):
        """Check we redirect to the canonical URL"""
        view = api.content.get_view("listing_view", self.folder, self.request)
        self.assertIsInstance(view, CollectionListingView)
        self.assertEqual(
            view(), f"{self.folder.absolute_url()}/@@app-image-bank-collection"
        )

    def test_menu_view(self):
        """Check we redirect to the canonical URL"""
        view = api.content.get_view("menu-image-bank", self.folder, self.request)
        self.assertIsInstance(view, ImageBankCollectionMenuView)

    def test_can_upload(self):
        view = self.get_view()
        self.assertFalse(view.can_upload())

        with api.env.adopt_roles(["Contributor"]):
            self.assertTrue(view.can_upload())

        view = api.content.get_view("image-bank-upload-form", self.folder, self.request)
        self.assertIsInstance(view, ImageBankFolderUploadForm)

    def test_can_edit(self):
        view = api.content.get_view("panel-edit-collection", self.folder, self.request)
        self.assertIsInstance(view, PanelEditCollectionView)

    def test_edit_panel_adapter(self):
        adapter = IPanelCreateCollectionViewSchema(self.folder)
        self.assertIsInstance(adapter, CollectionSchemaAdapter)

        self.assertEqual(adapter.title, self.folder.title)
        self.assertEqual(adapter.description, self.folder.description)
        self.assertListEqual(adapter.maintenance, [])
        self.assertListEqual(adapter.visibility, [])
        self.assertListEqual(adapter.contribution, [])

        adapter.maintenance = ["user:admin", "group:editors"]
        self.assertListEqual(adapter.maintenance, ["admin", "editors"])
        adapter.maintenance = ["user:admin"]
        self.assertListEqual(adapter.maintenance, ["admin"])
        adapter.maintenance = ["group:editors", "user:qa.admin"]
        self.assertListEqual(adapter.maintenance, ["editors", "qa.admin"])
        adapter.maintenance = []
        self.assertListEqual(adapter.maintenance, [])

        adapter.visibility = ["user:admin", "group:editors"]
        self.assertListEqual(adapter.visibility, ["admin", "editors"])

        adapter.visibility = None
        self.assertListEqual(adapter.visibility, [])
