"""Represents the entire JSON file generated by the aws iam get-account-authorization-details command."""
# Copyright (c) 2020, salesforce.com, inc.
# All rights reserved.
# Licensed under the BSD 3-Clause license.
# For full license text, see the LICENSE file in the repo root
# or https://opensource.org/licenses/BSD-3-Clause
import logging
from policy_sentry.querying.all import get_all_service_prefixes
from policy_sentry.querying.actions import get_all_action_links
from cloudsplaining.scan.managed_policy_detail import ManagedPolicyDetails
from cloudsplaining.scan.group_details import GroupDetailList
from cloudsplaining.scan.role_details import RoleDetailList
from cloudsplaining.scan.user_details import UserDetailList
from cloudsplaining.shared.exclusions import Exclusions, DEFAULT_EXCLUSIONS

all_service_prefixes = get_all_service_prefixes()
logger = logging.getLogger(__name__)


# pylint: disable=too-many-instance-attributes
class AuthorizationDetails:
    """
    Represents the entire JSON file generated by the aws iam get-account-authorization-details command.
    """

    def __init__(self, auth_json, exclusions=DEFAULT_EXCLUSIONS):
        self.auth_json = auth_json

        if not isinstance(exclusions, Exclusions):
            raise Exception("For exclusions, please provide an object of the Exclusions type")
        self.exclusions = exclusions

        self.policies = ManagedPolicyDetails(auth_json.get("Policies", None), exclusions)

        # New Authorization file stuff
        self.group_detail_list = GroupDetailList(auth_json.get("GroupDetailList"), self.policies, exclusions)
        self.user_detail_list = UserDetailList(auth_json.get("UserDetailList"), self.policies,
                                                   self.group_detail_list, exclusions)
        self.role_detail_list = RoleDetailList(auth_json.get("RoleDetailList"), self.policies, exclusions)

    @property
    def inline_policies(self):
        """Return inline policy details"""
        results = {}
        results.update(self.group_detail_list.inline_policies_json)
        results.update(self.role_detail_list.inline_policies_json)
        results.update(self.user_detail_list.inline_policies_json)
        return results

    @property
    def links(self):
        """Return a dictionary of the action names as keys and their API documentation links as values"""
        results = {}
        unique_action_names = set()
        # unique_action_names will be in the InfrastructureModification block for any given policy.
        # So if it shows up in ResourceExposure, it will also be in InfrastructureModification
        # Or if it shows up in DataExfiltration or PrivilegeEscalation, it will also be in InfrastructureModification
        # Let's create a set of unique_action_names that are in InfrastructureModification
        # First, let's get them from ManagedPolicyDetails
        # Then, the inline policies from GroupDetails, RoleDetails, and UserDetails
        unique_action_names.update(self.group_detail_list.all_infrastructure_modification_actions_by_inline_policies)
        unique_action_names.update(self.role_detail_list.all_infrastructure_modification_actions_by_inline_policies)
        unique_action_names.update(self.user_detail_list.all_infrastructure_modification_actions_by_inline_policies)
        unique_action_names.update(self.policies.all_infrastructure_modification_actions)

        unique_action_names = sorted(unique_action_names)
        all_action_links = get_all_action_links()

        for action in unique_action_names:
            if action in all_action_links:
                results[action] = all_action_links[action]
        return results

    @property
    def results(self):
        """Get the new JSON format of the Principals data"""
        results = {
            "groups": self.group_detail_list.json,
            "users": self.user_detail_list.json,
            "roles": self.role_detail_list.json,
            "aws_managed_policies": self.policies.json_large_aws_managed,
            "customer_managed_policies": self.policies.json_large_customer_managed,
            "inline_policies": self.inline_policies,
            "exclusions": self.exclusions.config,
            "links": self.links
        }
        return results
