#!/usr/bin/env python
# -*- coding: utf-8 -*-
from enum import Enum

from aws_xray_sdk.core import xray_recorder as xray


class SLaterRoleEntitlementLevel(Enum):
    READ_ONLY = 1
    READ_WRITE = 2
    CDS_READ_WRITE = 3
    FINOPS_READ_WRITE = 3
    FULL_ADMIN = 4
    UNAUTHORIZED = 5


class SLaterUserEntitlementLevel(Enum):
    SLATER_UNAUTHORIZED = 0
    SLATER_READER = SLaterRoleEntitlementLevel.READ_ONLY.value
    SLATER_WRITER = SLaterRoleEntitlementLevel.READ_WRITE.value
    SLATER_CDS_WRITER = SLaterRoleEntitlementLevel.CDS_READ_WRITE.value
    SLATER_FINOPS_WRITER = SLaterRoleEntitlementLevel.FINOPS_READ_WRITE.value
    SLATER_ADMIN = SLaterRoleEntitlementLevel.FULL_ADMIN.value


@xray.capture()
class SLaterAuth(object):
    """Validate if a user is in the correct slack usergroups.

    Each slater client function has a entitlement level requirement.
    If the user's entitlement level is equal to or greater than the function's
    requirements, the user is 'authorized'

    SLaterUX MVP C.R.U.D. follow these rules:

       (C)reate > slater-writers > SLaterUserEntitlementLevel.SLATER_WRITER
       (R)ead   > any valid slack member > SLaterUserEntitlementLevel.SLATER_READER
       (U)pdate > slater-writers > SLaterUserEntitlementLevel.SLATER_WRITER
       (D)elete > slater-admins > SLaterUserEntitlementLevel.SLATER_ADMIN

       * See SLater.slater_authorized_usergroup_handles in environments/unit.ini

    >>> admin_user_id: str = "U0EKDSZE2"
    >>> writer_user_id: str = "ULN1AUW6R"
    >>> read_only_id: str = "U2JLW7KBK"

    >>> from iobot.slack import Agent
    >>> client = slack_sdk.WebClient(token=testing.slack_bearer_token())
    >>> msg_agent = Agent(log,boto_session,client,config_file='environments/unit.ini', entitlement_level=Agent.entitlement_levels().UNRESTRICTED)

    >>> SLaterAuth(log, msg_agent, admin_user_id).GetEntitlement()
    <SLaterUserEntitlementLevel.SLATER_ADMIN: 4>

    >>> SLaterAuth(log, msg_agent, writer_user_id).GetEntitlement()
    <SLaterUserEntitlementLevel.SLATER_WRITER: 2>

    >>> SLaterAuth(log, msg_agent, read_only_id).GetEntitlement()
    <SLaterUserEntitlementLevel.SLATER_READER: 1>
    """
    @xray.capture()
    def __init__(self, log: dict, msg_agent: dict, slack_user_id: str) -> None:
        slater_groups = msg_agent.config['SLater']['slater_authorized_usergroup_handles'].split(
            ',')
        log.debug(f'groups in config: {slater_groups}')

        slater_slack_groups: list = msg_agent.list_usergroups(
            filters=slater_groups, include_users='true')
        log.debug(f'resolved groups: {slater_slack_groups}')

        entitlement_level: Enum = SLaterUserEntitlementLevel.SLATER_READER
        for group in slater_slack_groups:
            log.debug(
                f'checking group: {group["handle"]} for user: {slack_user_id}: {slack_user_id in group["users"]}')
            if slack_user_id in group['users']:
                if 'writer' in group['handle']:
                    if SLaterUserEntitlementLevel.SLATER_WRITER.value > entitlement_level.value:
                        entitlement_level = SLaterUserEntitlementLevel.SLATER_WRITER
                elif 'admin' in group['handle']:
                    if SLaterUserEntitlementLevel.SLATER_ADMIN.value > entitlement_level.value:
                        entitlement_level = SLaterUserEntitlementLevel.SLATER_ADMIN
                elif 'slater-cds' in group['handle']:
                    if SLaterUserEntitlementLevel.SLATER_CDS_WRITER.value > entitlement_level.value:
                        entitlement_level = SLaterUserEntitlementLevel.SLATER_CDS_WRITER
                elif 'slater-finops' in group['handle']:
                    if SLaterUserEntitlementLevel.SLATER_FINOPS_WRITER.value > entitlement_level.value:
                        entitlement_level = SLaterUserEntitlementLevel.SLATER_FINOPS_WRITER

        log.debug(f'user entitlement level set to: {entitlement_level}')
        self.entitlement_level = entitlement_level

    @xray.capture()
    def GetEntitlement(self) -> Enum:
        return self.entitlement_level
