#!/usr/bin/env python

from argparse import ArgumentParser
import logging
import os
import site

site.addsitedir(os.path.dirname(os.path.abspath(__file__)))

from lib.qc.bait.prism.ods import ODS
from quic_py_libs import common as ldap_group

logger = logging.getLogger(__name__)


class UserValidator(object):

    SUPER_GROUP = "linuxCM.accessExceptions"

    def __init__(self, user, components):
        self.user = user
        self.components = components
        self.team_by_component = self.get_integration_team()
        self.members_by_component = self.get_integration_members()

    def get_integration_team(self):
        with ODS() as odb:
            team_by_component = {
                component: odb.get_component_int_team(component)
                for component in self.components}
        logger.info("Integration Teams:{}".format(team_by_component))
        return team_by_component

    def is_super_group_member(self):
        return self.user in ldap_group.getMembers(self.SUPER_GROUP)

    def get_integration_members(self):
        return {
            component: ldap_group.getMembers(int_team)
            if int_team else None
            for component, int_team in list(self.team_by_component.items())}

    def get_common_members(self):
        users = set()
        for comp, members in list(self.members_by_component.items()):
            if members:
                if not users:
                    users = set(members)
                    continue
                # Expands a users = users & members
                # Finds the common elements of users and members
                users &= set(members)
        return users

    def is_user_allowed(self):
        if self.is_super_group_member():
            logger.info("User:{} is part of group:{}, Hence allowing".format(
                self.user, self.SUPER_GROUP))
            return True
        comp_without_int_team = self.get_components_without_integration_team()
        if comp_without_int_team:
            logger.info("Could not find integration team for"
                        " components:{}".format(comp_without_int_team))
            return False
        common_members = self.get_common_members()
        logger.info("Common members found in integration"
                    " teams:{}".format(common_members))
        return self.user in common_members

    def get_components_without_integration_team(self):
        return [comp for comp, members in list(self.members_by_component.items())
                if not members]


def validate_user(user, components):
    uv = UserValidator(user, components)
    if not uv.is_user_allowed():
        raise Exception(
            "User:{} is not part of component "
            "integration lists:{}".format(
                user, dict(uv.team_by_component)))
    logger.info("Valid username:{}".format(user))


if __name__ == "__main__":

    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s %(levelname)-8s %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S')

    parser = ArgumentParser()
    parser.add_argument("user", help="user to check")
    parser.add_argument("components", nargs='+', help="separated by space")
    args = parser.parse_args()

    validate_user(args.user, args.components)
