from collections import defaultdict
from collections import OrderedDict
from io import BytesIO
from plone import api
from ploneintranet.workspace.interfaces import IWorkspaceFolder
from Products.Five import BrowserView

import openpyxl


class WorkspaceMembershipReport(BrowserView):
    @property
    def workspaces(self):
        pc = api.portal.get_tool("portal_catalog")
        brains = pc.unrestrictedSearchResults(
            object_provides=IWorkspaceFolder.__identifier__
        )
        return [i.getObject() for i in brains]

    def principals_by_role(self, ws):
        panel_view = api.content.get_view(
            context=ws, name="panel-related-workspaces", request=self.request
        )
        principals = panel_view.get_sorted_principals()
        principals_by_role = defaultdict(list)
        for principal in principals:
            roles = panel_view.get_principal_roles(
                principal, omit_default_policy_role=False
            )
            for role in roles:
                principals_by_role[role].append(principal.getId())
        return principals_by_role

    def workspace_details_and_roles(self, ws):
        principals_by_role = self.principals_by_role(ws)
        principals = set()
        for principal_list in principals_by_role.values():
            for principal in principal_list:
                principals.add(principal)
        sorted_principals = sorted(list(principals))
        all_members = ", ".join(sorted_principals)
        ws_details = {
            "id": ws.id,
            "title": ws.title,
            "participant_policy": ws.participant_policy,
            "join_policy": ws.join_policy,
            "visible_to_intranet_users": ws.visible_to_intranet_users,
            "accessible_to_intranet_users": ws.accessible_to_intranet_users,
            "all_members": all_members,
        }
        roles = list(principals_by_role.keys())
        for role in roles:
            ws_details[role] = ", ".join(principals_by_role[role])
        return ws_details, roles

    def to_excel(self, data, roles):
        workbook = openpyxl.Workbook()
        sheet = workbook.active
        fields = OrderedDict(
            [
                ("id", "ID"),
                ("title", "Title"),
                ("description", "Description"),
                ("join_policy", "Join Policy"),
                ("participant_policy", "Participant Policy"),
                ("all_members", "All Members"),
            ]
        )
        for role in roles:
            fields[role] = role

        # Header row
        for col_index, field in enumerate(fields, 1):
            sheet.cell(1, col_index, fields[field])

        for row_index, row in enumerate(data, 2):
            for col_index, field in enumerate(fields, 1):
                sheet.cell(row_index, col_index, row.get(field, ""))
        output = BytesIO()
        workbook.save(output)
        return output.getvalue()

    def all_workspace_details_and_roles(self):
        all_roles = set()
        all_details = []
        for workspace in self.workspaces:
            details, roles = self.workspace_details_and_roles(workspace)
            all_roles = all_roles | set(roles)
            all_details.append(details)
        sorted_roles = sorted(list(all_roles))
        return all_details, sorted_roles

    def __call__(self):
        workspace_details, roles = self.all_workspace_details_and_roles()
        excel = self.to_excel(workspace_details, roles)
        self.request.response.setHeader("Content-type", "application/vnd.ms-excel")
        self.request.response.setHeader(
            "Content-Disposition",
            "attachment; filename=workspace-membership-report.xls",
        )
        return excel
