"""Describe Organizations."""
import logging
import os

import emoji
from colorama import Fore

import json
import logging
from pathlib import Path

from colorama import Fore


def save_results(results, filename, directory_path="."):
    """
    Save results to a file.

    :param directory_path:
    :param results:
    :param filename:

    :return: None. Saves results to a file.
    """
    if not Path.exists(Path(directory_path)):
        Path.mkdir(Path(directory_path))
        logging.debug(f"Directory {directory_path} created")
    with open(f"{directory_path}/{filename}", "w") as f:
        json.dump(results, fp=f, indent=4)
        print(
            f"{Fore.YELLOW}ℹ️  The accounts are stored in {directory_path}/{filename} {Fore.RESET}"
        )


def find_ou_name(ous, search_id):
    """
    Find OU Name in list.

    :param ous:
    :param search_id:
    :return:
    """
    for a in ous:
        if a["Id"] == search_id:
            return a["Name"]


def find_ou_index(ous, search_id):
    """
    Find OU Name in list.

    :param ous:
    :param search_id:
    :return:
    """
    for a in ous:
        if a["Id"] == search_id:
            return a


# search ou in map
def search_ou_map(map_ou: dict, ou_id, level=0, tree="."):
    """
    Search OU in map.

    :param tree:
    :param level:
    :param map_ou:
    :param ou_id:
    :return:
    """
    for a in map_ou.keys():
        # print(f'Searching {ou_id}... in {map_ou[a]["nestedOus"]}')

        if len(map_ou[a]["nestedOus"]) > 0:
            level += 1
            tree += f".{a}"

            if ou_id in map_ou[a]["nestedOus"].keys():
                print(f"Find in {a}, for {ou_id}, level {level}")
                # search_ou_map(map_ou=map_ou[a]["nestedOus"], ou_id=ou_id, level=level, tree=tree)

                return map_ou[a]
            # else:
            # search_ou_map(map_ou=map_ou[a]["nestedOus"], ou_id=ou_id, level=level, tree=tree)
    return None


def init_org_complete(root_id, org, list_ous, ):
    organizations_complete = {
        "rootId": root_id,
        "masterAccountId": org['MasterAccountId'],
        "noOutAccounts": [],
        "organizationalUnits": {}
    }

    # Iterate in ous for getting ous tree
    for a, i in zip(list_ous, range(len(list_ous))):

        for p in a["Parents"]:
            if p["Type"] == "ROOT":
                organizations_complete["organizationalUnits"][a['Name']] = {
                    "Id": a['Id'],
                    "Name": a['Name'],
                    "accounts": {},
                    "nestedOus": {}}
    return organizations_complete


# create organization complete map
def map_organizations_complete(organizations_complete: dict,
                               list_ous, llist_accounts,
                               reference_outs_list,
                               ):
    """
    Create complete mapper file.


    :param reference_outs_list:
    :param organizations_complete:
    :param list_ous:
    :param llist_accounts:
    :return:
    """

    # Iterate in ous for getting ous tree
    for a, i in zip(list_ous, range(len(list_ous))):

        for p in a["Parents"]:

            if p["Type"] == "ORGANIZATIONAL_UNIT":

                o = find_ou_name(reference_outs_list, p['Id'])

                if o not in organizations_complete["organizationalUnits"].keys():
                    print("Nested Ou", o)
                    p = search_ou_map(organizations_complete["organizationalUnits"], ou_id=o)
                    new_list_ous = p["nestedOus"]

                    new_list_ous = plop_dict_out(ous_list=list_ous, ou=new_list_ous)
                    organizations_complete = map_organizations_complete(organizations_complete=organizations_complete,
                                                                        list_ous=new_list_ous,
                                                                        llist_accounts=llist_accounts,
                                                                        reference_outs_list=reference_outs_list)

                else:
                    organizations_complete["organizationalUnits"][o]["nestedOus"][
                        find_ou_name(reference_outs_list, a['Id'])] = {

                        "Id": a['Id'],
                        "Name": a['Name'],
                        "accounts": [],
                        "nestedOus": {}

                    }
                    # print(organizations_complete["organizationalUnits"][o]["nestedOus"])
                    if len(organizations_complete["organizationalUnits"][o]["nestedOus"]) > 0:
                        new_list_ous = organizations_complete["organizationalUnits"][o]["nestedOus"]

                        new_list_ous = plop_dict_out(ous_list=list_ous, ou=new_list_ous)
                        organizations_complete = map_organizations_complete(
                            organizations_complete=organizations_complete,
                            list_ous=new_list_ous,
                            llist_accounts=llist_accounts,
                            reference_outs_list=reference_outs_list)

    return organizations_complete


def plop_dict_out(ous_list: list, ou, ):
    """
    Clean list.
    
    :param ous_list: 
    :param ou: 
    :return: 
    """
    for o in ou.keys():

        # for c in ou.keys():
        for unit in ous_list:
            if unit["Id"] == ou[o]["Id"]:
                ous_list.remove(unit)

    return ous_list


def set_accounts_tree(llist_accounts, organizations_complete, list_ous):
    """
    Set accounts tree.

    :param llist_accounts:
    :param organizations_complete:
    :param list_ous:
    :return:
    """
    # Iterate in list accounts to get parent ous
    for c, i in zip(llist_accounts, range(len(llist_accounts))):
        # print(f"\n    aa_{i}= OrganizationsAccount(\"{c['account']}\")", file=f)
        for p in c["parents"]:
            if p["Type"] == "ROOT":
                organizations_complete["noOutAccounts"].append(
                    {
                        "account": c["account"],
                        "name": c['name']
                    }
                )

            for o, j in zip(list_ous, range(len(list_ous))):
                if p["Id"] == o["Id"] and p["Type"] == "ORGANIZATIONAL_UNIT":
                    organizations_complete["organizationalUnits"][find_ou_name(list_ous, o['Id'])]["accounts"][
                        c['name']] = {
                        "account": c["account"],
                        "name": c['name']
                    }

    return organizations_complete


root = 'r-w3ow'
org_data = {'Id': 'o-9tlhkjyoii', 'Arn': 'arn:aws:organizations::029921763173:organization/o-9tlhkjyoii',
            'FeatureSet': 'ALL',
            'MasterAccountArn': 'arn:aws:organizations::029921763173:account/o-9tlhkjyoii/029921763173',
            'MasterAccountId': '029921763173',
            'MasterAccountEmail': 'velez94@protonmail.com',
            'AvailablePolicyTypes': [{'Type': 'SERVICE_CONTROL_POLICY', 'Status': 'ENABLED'}]}

ous = [
    {'Id': 'ou-w3ow-oegm0al0',
     'Arn': 'arn:aws:organizations::029921763173:ou/o-9tlhkjyoii/ou-w3ow-oegm0al0',
     'Name': 'Research', 'Parents': [{'Id': 'r-w3ow', 'Type': 'ROOT'}]},
    {'Id': 'ou-w3ow-k24p2opx', 'Arn': 'arn:aws:organizations::029921763173:ou/o-9tlhkjyoii/ou-w3ow-k24p2opx',
     'Name': 'Dev',
     'Parents': [{'Id': 'r-w3ow', 'Type': 'ROOT'}]
     },
    {'Id': 'ou-w3ow-93hiq3zr', 'Arn': 'arn:aws:organizations::029921763173:ou/o-9tlhkjyoii/ou-w3ow-93hiq3zr',
     'Name': 'Core',
     'Parents': [{'Id': 'r-w3ow', 'Type': 'ROOT'}]
     },
    {'Id': 'ou-w3ow-5qsqi8b5', 'Arn': 'arn:aws:organizations::029921763173:ou/o-9tlhkjyoii/ou-w3ow-5qsqi8b5',
     'Name': 'Custom', 'Parents': [{'Id': 'r-w3ow', 'Type': 'ROOT'}]},
    {'Id': 'ou-w3ow-w7dzhzcz', 'Arn': 'arn:aws:organizations::029921763173:ou/o-9tlhkjyoii/ou-w3ow-w7dzhzcz',
     'Name': 'Shared', 'Parents': [{'Id': 'r-w3ow', 'Type': 'ROOT'}]},
    {'Id': 'ou-w3ow-i9xzgb9x', 'Arn': 'arn:aws:organizations::029921763173:ou/o-9tlhkjyoii/ou-w3ow-i9xzgb9x',
     'Name': 'NetstedOU', 'Parents': [{'Id': 'ou-w3ow-5qsqi8b5', 'Type': 'ORGANIZATIONAL_UNIT'}]},
    {'Id': 'ou-w3ow-i9xzgxxx', 'Arn': 'arn:aws:organizations::029921763173:ou/o-9tlhkjyoii/ou-w3ow-i9xzxxxx',
     'Name': 'NetstedOU2', 'Parents': [{'Id': 'ou-w3ow-5qsqi8b5', 'Type': 'ORGANIZATIONAL_UNIT'},
                                       {'Id': 'ou-w3ow-i9xzgb9x', 'Type': 'ORGANIZATIONAL_UNIT'}]},
    {'Id': 'ou-w3ow-i9xzgxx3', 'Arn': 'arn:aws:organizations::029921763173:ou/o-9tlhkjyoii/ou-w3ow-i9xzxxxx',
     'Name': 'NetstedOU3', 'Parents': [{'Id': 'ou-w3ow-5qsqi8b5', 'Type': 'ORGANIZATIONAL_UNIT'},
                                       {'Id': 'ou-w3ow-i9xzgb9x', 'Type': 'ORGANIZATIONAL_UNIT'},
                                       {'Id': 'ou-w3ow-i9xzgxxx', 'Type': 'ORGANIZATIONAL_UNIT'}]}

]

accounts = [
    {'account': '884478634998', 'name': 'Log archive',
     'parents': [{'Id': 'ou-w3ow-93hiq3zr', 'Type': 'ORGANIZATIONAL_UNIT'}]},
    {'account': '582441254763', 'name': 'Prod',
     'parents': [{'Id': 'ou-w3ow-5qsqi8b5', 'Type': 'ORGANIZATIONAL_UNIT'}]},
    {'account': '895882538541', 'name': 'Audit',
     'parents': [{'Id': 'ou-w3ow-93hiq3zr', 'Type': 'ORGANIZATIONAL_UNIT'}]},
    {'account': '105171185823', 'name': 'DevSecOps',
     'parents': [{'Id': 'ou-w3ow-w7dzhzcz', 'Type': 'ORGANIZATIONAL_UNIT'}]},
    {'account': '994261317734', 'name': 'LabVelCT',
     'parents': [{'Id': 'ou-w3ow-k24p2opx', 'Type': 'ORGANIZATIONAL_UNIT'}]},
    {'account': '155794986228', 'name': 'SharedServices',
     'parents': [{'Id': 'ou-w3ow-w7dzhzcz', 'Type': 'ORGANIZATIONAL_UNIT'}]},
    {'account': '029921763173', 'name': 'Alejandro Velez', 'parents': [{'Id': 'r-w3ow', 'Type': 'ROOT'}]},
    {'account': '571340586587', 'name': 'Dev',
     'parents': [{'Id': 'ou-w3ow-k24p2opx', 'Type': 'ORGANIZATIONAL_UNIT'}]}]

groups = [
    {'group_id': '9a672b3314-f46f413e-44d7-4d3d-918b-f86721413097', 'group_name': 'AWSSecurityAuditors',
     'members': []},
    {'group_id': '9a672b3314-c481fbee-8062-432a-8b87-eeaa36b763a8', 'group_name': 'AWSLogArchiveAdmins',
     'members': []},
    {'group_id': '318bc590-a071-70f5-63f6-ab21233e4e33', 'group_name': 'DevSecOps_Admins', 'members': [
        {'IdentityStoreId': 'd-9a672b3314', 'MembershipId': '51bbe5a0-7001-7010-d7c0-46f5044d014e',
         'GroupId': '318bc590-a071-70f5-63f6-ab21233e4e33',
         'MemberId': {'UserId': '010be510-1061-70df-8274-96526bc47eb7', 'UserName': 'DevSecOpsAdm'}}]},
    {'group_id': '9a672b3314-ff479c57-03cb-440e-8902-be8ea9d7d25b', 'group_name': 'AWSLogArchiveViewers',
     'members': []},
    {'group_id': '9a672b3314-b858476a-2ef9-4018-90e7-29e5e4bc4388', 'group_name': 'AWSSecurityAuditPowerUsers',
     'members': []},
    {'group_id': '9a672b3314-faf36c54-a70c-4db6-aefc-e5ac006ad5a1', 'group_name': 'AWSAuditAccountAdmins',
     'members': []},
    {'group_id': '9a672b3314-f8065505-3174-4d46-a1b4-f134fd0ca2fc', 'group_name': 'AWSAccountFactory', 'members': [
        {'IdentityStoreId': 'd-9a672b3314', 'MembershipId': 'e18bb590-9031-70a0-5469-42c9799e8a6b',
         'GroupId': '9a672b3314-f8065505-3174-4d46-a1b4-f134fd0ca2fc',
         'MemberId': {'UserId': '9a672b3314-bd21c8b3-1aa0-4922-9374-92321b4979bf',
                      'UserName': 'velez94@protonmail.com'}}]},
    {'group_id': '9a672b3314-7f743f07-169a-4172-bdbc-561e7908e463', 'group_name': 'AWSServiceCatalogAdmins',
     'members': []},
    {'group_id': '9a672b3314-43117aac-887b-48ee-af49-b6b6cd059199', 'group_name': 'AWSControlTowerAdmins',
     'members': [
         {'IdentityStoreId': 'd-9a672b3314', 'MembershipId': 'e14b3500-3051-70b2-25b7-d5729d383061',
          'GroupId': '9a672b3314-43117aac-887b-48ee-af49-b6b6cd059199',
          'MemberId': {'UserId': '9a672b3314-bd21c8b3-1aa0-4922-9374-92321b4979bf',
                       'UserName': 'velez94@protonmail.com'}}]}]

account_assignments = {'Master': [{'AccountId': '029921763173',
                                   'PermissionSetArn': 'arn:aws:sso:::permissionSet/ssoins-66845289d6823727/ps-ab185f05acde5e90',
                                   'PrincipalType': 'GROUP',
                                   'PrincipalId': '9a672b3314-b858476a-2ef9-4018-90e7-29e5e4bc4388',
                                   'GroupName': 'AWSSecurityAuditPowerUsers',
                                   'PermissionSetName': 'AWSPowerUserAccess'},
                                  {'AccountId': '029921763173',
                                   'PermissionSetArn': 'arn:aws:sso:::permissionSet/ssoins-66845289d6823727/ps-7cc34a5a03379f6f',
                                   'PrincipalType': 'GROUP',
                                   'PrincipalId': '9a672b3314-f8065505-3174-4d46-a1b4-f134fd0ca2fc',
                                   'GroupName': 'AWSAccountFactory',
                                   'PermissionSetName': 'AWSServiceCatalogEndUserAccess'},
                                  {'AccountId': '029921763173',
                                   'PermissionSetArn': 'arn:aws:sso:::permissionSet/ssoins-66845289d6823727/ps-21058a9d1f62c7e2',
                                   'PrincipalType': 'GROUP',
                                   'PrincipalId': '9a672b3314-43117aac-887b-48ee-af49-b6b6cd059199',
                                   'GroupName': 'AWSControlTowerAdmins',
                                   'PermissionSetName': 'AWSAdministratorAccess'},
                                  {'AccountId': '029921763173',
                                   'PermissionSetArn': 'arn:aws:sso:::permissionSet/ssoins-66845289d6823727/ps-cf27b0efdc941a09',
                                   'PrincipalType': 'GROUP',
                                   'PrincipalId': '9a672b3314-f46f413e-44d7-4d3d-918b-f86721413097',
                                   'GroupName': 'AWSSecurityAuditors', 'PermissionSetName': 'AWSReadOnlyAccess'},
                                  {'AccountId': '029921763173',
                                   'PermissionSetArn': 'arn:aws:sso:::permissionSet/ssoins-66845289d6823727/ps-83e7c23c8b2df8b3',
                                   'PrincipalType': 'GROUP',
                                   'PrincipalId': '9a672b3314-7f743f07-169a-4172-bdbc-561e7908e463',
                                   'GroupName': 'AWSServiceCatalogAdmins',
                                   'PermissionSetName': 'AWSServiceCatalogAdminFullAccess'}],
                       'DevSecOps': [
                           {'AccountId': '105171185823',
                            'PermissionSetArn': 'arn:aws:sso:::permissionSet/ssoins-66845289d6823727/ps-ab185f05acde5e90',
                            'PrincipalType': 'GROUP',
                            'PrincipalId': '9a672b3314-b858476a-2ef9-4018-90e7-29e5e4bc4388',
                            'GroupName': 'AWSSecurityAuditPowerUsers', 'PermissionSetName': 'AWSPowerUserAccess'},
                           {'AccountId': '105171185823',
                            'PermissionSetArn': 'arn:aws:sso:::permissionSet/ssoins-66845289d6823727/ps-21058a9d1f62c7e2',
                            'PrincipalType': 'GROUP', 'PrincipalId': '318bc590-a071-70f5-63f6-ab21233e4e33',
                            'GroupName': 'DevSecOps_Admins',
                            'PermissionSetName': 'AWSAdministratorAccess'},
                           {'AccountId': '105171185823',
                            'PermissionSetArn': 'arn:aws:sso:::permissionSet/ssoins-66845289d6823727/ps-21058a9d1f62c7e2',
                            'PrincipalType': 'USER',
                            'PrincipalId': '81bb65b0-40f1-7082-2b16-83138563c37b',
                            'UserName': 'w.alejovl+devsecops-labs@gmail.com',
                            'PermissionSetName': 'AWSAdministratorAccess'},
                           {'AccountId': '105171185823',
                            'PermissionSetArn': 'arn:aws:sso:::permissionSet/ssoins-66845289d6823727/ps-cf27b0efdc941a09',
                            'PrincipalType': 'GROUP',
                            'PrincipalId': '9a672b3314-f46f413e-44d7-4d3d-918b-f86721413097',
                            'GroupName': 'AWSSecurityAuditors', 'PermissionSetName': 'AWSReadOnlyAccess'},
                           {'AccountId': '105171185823',
                            'PermissionSetArn': 'arn:aws:sso:::permissionSet/ssoins-66845289d6823727/ps-c6046bbbf15aaafc',
                            'PrincipalType': 'GROUP',
                            'PrincipalId': '9a672b3314-43117aac-887b-48ee-af49-b6b6cd059199',
                            'GroupName': 'AWSControlTowerAdmins',
                            'PermissionSetName': 'AWSOrganizationsFullAccess'}]}

organizations_complete_f = map_organizations_complete(
    organizations_complete=init_org_complete(org=org_data, root_id=root, list_ous=ous),
    llist_accounts=accounts, list_ous=ous, reference_outs_list=ous.copy()
)
organizations_complete_f = set_accounts_tree(llist_accounts=accounts,
                                             organizations_complete=organizations_complete_f, list_ous=ous)
save_results(results=organizations_complete_f, filename="organizations_complete_state.json")
