from .runner_base import BaseRunner
from oaaclient.templates import CustomIdPProvider
from oaaclient.templates import OAAPropertyType
from oaa import oaa_utils
import sys
import logging
from oaaclient.client import OAAClientError
logger = logging.getLogger(__name__)

#########################################################################
#  The Main CLI object. We put it here so that the entrypoint script is
#  simpler.
#########################################################################


class IdPRunner(BaseRunner):

    runner_type = 'IDP'

    def run(self):
        """Import a custom IdP

        This should work similar to run-hris.

        :returns: TODO

        """
        # ingesting a custom IdP
        # get client
        # create
        # create a CustomIdPProvider to represent your IdP. This can be named
        # generically or specific to the environment if you have

        # multiple namespaces to model. idp_type will typically be the
        # technology/vendor for the provider.
        provider_name = self._provider_name
        idp = CustomIdPProvider("My IdP", domain="example.com",
                                idp_type="custom_idp")

        # Add custom property this is the same as for HRIS
        idp.property_definitions.define_user_property("region",
                                                      OAAPropertyType.STRING)
        idp.property_definitions.define_user_property("is_contractor",
                                                      OAAPropertyType.BOOLEAN)

        # What is the minimum set of attributes for user on a custom IdP?
        idp.add_user("mrichardson",
                     full_name="Michelle Richardson",
                     email="mrichardson@example.com")

        evargas_user = idp.add_user("evargas")
        evargas_user.full_name = "Elizabeth Vargas"
        evargas_user.email = "evargas@example.com"

        # Create Groups
        idp.add_group("developers")
        idp.add_group("sec-ops")
        idp.add_group("everyone", full_name="All Company Employees")

        # different ways to add users to groups and groups to users

        for username in idp.users:
            idp.users[username].add_groups(["everyone"])

        evargas_user.add_groups(["developers", "sec-ops"])
        idp.users["mrichardson"].add_groups(["developers"])

        # Veza CustomIdP supports tracking the AWS Roles a user can assume. For
        # users who can assume roles Veza can calculate
        # their effective permissions to AWS resources based on the role(s)
        # roles are added by ARN
        arn_list = [
            "arn:aws:iam::123456789012:role/role001",
            "arn:aws:iam::123456789012:role/role002"
        ]
        idp.users["mrichardson"].add_assumed_role_arns(arn_list)

        veza_con = oaa_utils.get_oaa_client(runner=self)

        # get or create provider
        provider = veza_con.get_provider(provider_name)
        try:
            data_source_name = f"{idp.name} ({idp.idp_type})"
            response = veza_con.push_application(provider['name'],
                                                 data_source_name=data_source_name, # noqa E501
                                                 application_object=idp,
                                                 save_json=True
                                                 )

            if response.get("warnings", None):
                # Veza may return warnings on a successful uploads. These are
                # informational warnings that did not stop the processing
                # of the OAA data but may be important, for example: AWS role
                # ARNs assigned to users that Veza has not discovered
                logger.warn("-- Push succeeded with warnings:")

                for e in response["warnings"]:
                    logger.warn(f"  - {e}")
        except OAAClientError as e:
            logger.error(f"-- Error: {e.error}: {e.message} ({e.status_code})",
                         file=sys.stderr)

            if hasattr(e, "details"):
                for d in e.details:
                    logger.eror(f"  -- {d}", file=sys.stderr)
