# Copyright 2020-2025 Ping Identity Corporation. All Rights Reserved
#
# This code is to be used exclusively in connection with Ping Identity
# Corporation software or services. Ping Identity Corporation only offers
# such software or services to legal entities who have entered into a
# binding license agreement with Ping Identity Corporation.

# -*- coding: utf-8 -*-

# load tasks used by configuration file
from pyrock.tests.stress.am.authn_rest.tasks.mytasks import EnablePrometheusMonitoring
from pyrock.tasks.scenario.gatling import GatlingTask
from pyrock.tasks.deployment.configuration_idm import PrepareWorkloadTask

# Python imports
import os
from datetime import date

# Framework imports
from pyrock.lib.PyRockRun import get_pyrock_run
from pyrock.lib.scheduler.tasks.OverseerTask import OverseerTask
from pyrock.lib.scheduler.tasks.StepTask import StepTask
from shared.lib.cloud_utils import kubectl
from shared.lib.utils.exception import FailException
from shared.lib.utils.constants import IGNORE_TIMEOUT

pyrock_run = get_pyrock_run()


class MakeRefreshTokenFeederTask(OverseerTask):
    """Generate feeders on overseer"""

    @property
    def command(self):
        return "/lodestar/pyrock/shared/scripts/am/bbc_refresh_token_feeder.sh"


class ImportRefreshTokenTask(StepTask):
    """make and import refresh tokens to CTS"""

    namespace = None
    template_file_name = None
    local_template_path = None
    remote_template_path = None
    remote_ldif_path = None
    source_pod = None

    def pre(self):
        if pyrock_run.is_component(self.source_name):
            print("source (%s) is a component" % self.source_name)
        else:
            raise FailException("source (%s) must be a component" % self.source.instance_name)
        if self.source.component_type == "overseer":
            self.remote_template_path = os.path.join(self.get_option("out_dir"), "template")
            self.remote_ldif_path = self.get_option("ldif_file")
        else:
            raise FailException("source (%s) must be an overseer component" % self.source.instance_name)
        self.namespace = pyrock_run.get_namespace()
        self.source_pod = self.source.pods[0]
        self.template_file_name = f"{self.target.instance_name}.template"

    def step1(self):
        """Make sure overseer is not busy"""
        # TODO: architecture issue : how to put a lock on overseer during this task
        #       to make sure no other tasks will run (overseer status file is not updated because we do not send order)
        try:
            self.source.loop_until_ready()
        except FailException:
            raise FailException("Overseer is already busy and not ready to accept an order")

    def step2(self):
        """Generate ldif template"""
        next_year = date.today().year + 1
        template = get_current_template(pyrock_run.get_config_parser().data_init.num_entries, next_year)

        self.local_template_path = pyrock_run.get_shared_file_name(self.template_file_name)
        print(f"location : {self.local_template_path}")
        print("")
        print("------------")
        print(template)
        print("------------")
        print("")
        with open(self.local_template_path, "w") as fd:
            fd.write(template)

    def step3(self):
        """Create folder on overseer"""
        cmd = f"mkdir -p {self.remote_template_path}"
        kubectl(args=f"exec {self.source_pod.name} -- {cmd}", component=self.source)

    def step4(self):
        """Copy template to overseer"""
        cmd = f"cp {self.local_template_path} {self.source_pod.name}:{self.remote_template_path}"
        kubectl(args=cmd, component=self.source)

    def step5(self):
        """Generate ldif file on overseer"""
        template = os.path.join(self.remote_template_path, self.template_file_name)
        cmd = (
            f"exec {self.source_pod.name} -- {self.source.get_full_path('makeldif')}"
            f" --outputLdif {self.remote_ldif_path} {template}"
        )
        kubectl(args=cmd, max_time=IGNORE_TIMEOUT, component=self.source)

    def step6(self):
        """Import entries on first ds-cts pod mentioned as target"""
        cmd = f"exec {self.source_pod.name} --  {self.source.get_full_path('ldapmodify')}"
        cmd += f" --hostname {self.target.hostname} --port {self.target.component.ldap_port} --useStartTls --trustAll"
        cmd += f' --bindDn "{self.target.component.admin_user}" --bindPassword "{self.target.component.admin_password}"'
        cmd += f" --noPropertiesFile --no-prompt --continueOnError --numConnections 10 {self.remote_ldif_path}"
        kubectl(args=cmd, max_time=IGNORE_TIMEOUT, component=self.source)


def get_current_template(num_entries, next_year):
    return r"""define NUM_TOKENS=%s
branch: ou=tokens
objectClass: top
objectClass: organizationalUnit
ou: famrecords
subordinateTemplate: coreToken:[NUM_TOKENS]

template: coreToken
rdnAttr: coreTokenId
coreTokenId: <random:hex:28>
objectClass: top
objectClass: frCoreToken
coreTokenType: OAUTH
coreTokenDate02: 19700119123927.107Z
coreTokenString01: employeenumber,mail,profile,fr:idm:*
coreTokenString03: user.<sequential:0>
coreTokenString07: Bearer
coreTokenString08: /
coreTokenString09: oauth2
coreTokenString10: refresh_token
coreTokenString12: authorization_code
coreTokenTtlDate: %s1223215245.412+0200
coreTokenObject: \{"clientID":\["oauth2"\],"auth_level":0,"tokenName":\["refresh_token"\],"authModules":\["DataStore"\],"userName":\["{coreTokenString03}"\],"acr":\["0"\],"expireTime":\["4133947495000"\],"grant_type":\["authorization_code"\],"scope":\["employeenumber","mail","profile","fr:idm:*"\],"auth_time":\["1601286253"\],"realm":\["/"\],"id":\["{coreTokenId}"\],"tokenType":\["Bearer"\]}
""" % (
        num_entries,
        next_year,
    )
