"""
LDAP/AD-specific support for user property syncing
"""

from .userprofile import AllUserprofilesPropertySync
from DateTime import DateTime
from plone import api
from plone.memoize.view import memoize_contextless

import logging

logger = logging.getLogger(__name__)


class LDAPChangedUsersPropertySync(AllUserprofilesPropertySync):
    """This is an additional view, peculiar for pas.plugins.ldap,
    that tries to speed up the process of syncing
    the user properties by limiting the number of users we need to sync
    """

    _ldap_changed_attribute = "whenChanged"
    _ldap_username_attribute = "sAMAccountName"

    def _get_recent_ldap_user_ids(self):
        """Make a query to ldap and return just the userids"""
        last_sync = self.get_last_sync().strftime("%Y%m%d%H%M%S.0Z")
        queryFilter = f"({self._ldap_changed_attribute}>={last_sync})"
        ugm = self.external_source._ugm()
        return {
            x[1][self._ldap_username_attribute][0]
            for x in ugm.users.context.search(
                queryFilter=queryFilter, attrlist=[self._ldap_username_attribute]
            )
        }

    @property
    @memoize_contextless
    def principals(self):
        """Perform a custom LDAP query to limit the users who should be updated.

        Looks for users that have changed since the last sync,
        according to the _ldap_changed_attribute
        """
        last_sync = self.get_last_sync()
        if not last_sync:
            # First sync is always a full sync
            return super().principals

        logger.info(f"Looking for LDAP users changed since {last_sync}")

        userids = self._get_recent_ldap_user_ids()

        # Translate to membrane profiles
        mtool = api.portal.get_tool("membrane_tool")
        # Also add the users that have been created today
        # XXX This should be fixed, it is a very fragile solution
        userids.update(
            brain.getId
            for brain in mtool.searchResults(
                created={"range": "min", "query": DateTime() - 1}
            )
        )

        users = mtool.searchResults(exact_getUserId=list(userids))
        logger.info(f"Found {len(users)} users to update from LDAP")
        return [user.getObject() for user in users]
