#!/usr/bin/python3

##
# @file
# @ingroup rtctk_reusableComponents_deploymentDaemon_generator_app
#
# @brief Entry point for the rtctkDeploymentGen command line utility.
#
# @copyright
#   SPDX-FileCopyrightText: 2025-2026 European Southern Observatory (ESO) @n
#   SPDX-License-Identifier: LGPL-3.0-only

"""
This is the entry point for the deployment generator command line utility used to prepare Nomad
jobs for SRTC components.
"""

import os
import jinja2
import click
import json
import sys
import traceback
import re
from elt.log import CiiLogManager
from rtctk.common.cli.argtypes import (  # pylint: disable=E0401
    UriParamType,
    DpPathParamType,
)
from rtctk.deployment_daemon.generator.file_helper import (  # pylint: disable=E0401
    find_file,
)
from rtctk.deployment_daemon.generator.generate_nomad_job import (  # pylint: disable=E0401
    generate_nomad_job,
    generate_nomad_job_from_dp,
)
from rtctk.framework import (  # pylint: disable=E0611,E0401
    Uri,
    PersistentRepoIf,
)


RTCTK_JOB_NOMAD = "rtctk/rtctk_component.nomad.jinja2"
RTCTK_COMMON_SERVICE_CONSUL = "rtctk/rtctk_services.hcl.jinja2"
RTCTK_COMMON_SERVICE_NOMAD = "rtctk/rtctk_services.nomad.jinja2"


class Repo:
    """
    This class holds context information captured from command line arguments.
    """

    def __init__(self, node, stdout, datacenter, app_kill_timeout, user, sde):
        self.node = node
        self.stdout = stdout
        self.datacenter = datacenter
        self.app_kill_timeout = app_kill_timeout
        self.user = user
        self.sde = sde
        pass


@click.group()
@click.option(
    "--sde",
    default=Uri("consul://127.0.0.1:8500"),
    type=UriParamType(),
    show_default=True,
    help="service discovery URI endpoint. This overrides any",
)
@click.option(
    "--stdout",
    show_default=True,
    is_flag=True,
    default=False,
    help="Outputs to stdout instead of file.",
)
@click.option(
    "--datacenter",
    default="dc1",
    show_default=True,
    type=str,
    help="Contraints running the job to this DATACENTER.",
)
@click.option(
    "--app-kill-timeout",
    default="25s",
    show_default=True,
    type=str,
    help="Nomad job/application kill timeout.",
)
@click.option("--node", type=str, help="Contraints running the job to this NODE.")
@click.option(
    "--user",
    type=str,
    help="Runs the job as this user.",
)
@click.pass_context
def main(ctx, stdout, datacenter, app_kill_timeout, node, user, sde):
    """
    RTCTK Deployment Daemon Nomad/Consul Job Generator
    """
    ctx.obj = Repo(node, stdout, datacenter, app_kill_timeout, user, sde)
    pass


@main.command()
@click.argument(
    "component_name",
)
@click.argument(
    "command",
    required=False,
)
@click.argument("arguments", nargs=-1, type=str)
@click.option(
    "--no-services",
    show_default=True,
    is_flag=True,
    default=True,
    help="Creates a nomad job that provides no services",
)
@click.option(
    "--deployment-daemon",
    show_default=True,
    is_flag=True,
    default=False,
    help="Creates a nomad job for Deployment Daemon",
)
@click.pass_obj
def job(
    ctx,
    component_name: str,
    command: str,
    arguments: str,
    no_services: bool,
    deployment_daemon: bool,
):
    """Generate a nomad job file for running RTC Components.

    This program requires three strings as input:

    - COMPONENT_NAME: RTC Components name, the identifier of the component..

    - COMMAND: Executable application to run as part of this job.

    - ARGUMENTS: A string that contains quoted arguments to pass to the COMMAND.
      If you need to use arguments with  '-' character, please use '--' before that
      argument. Example:

      rtctkDeploymentGen job rtc_sup rtctkRtcSupervisor -- -d

    Exit Codes:
    * 11: --cid and COMPONET_NAME values are not the same.
    """
    """
    try:
        path = find_file(
            filepath=RTCTK_JOB_NOMAD,
        )
    except Exception as e:
        print(e, file=sys.stderr)
        traceback.print_exc()
        sys.exit(10)
    if not os.path.isfile(path):
        print(
            f"Could not find file: {RTCTK_JOB_NOMAD}. Please make sure the RTC Toolkit is installed"
            " correctly and that the CFGPATH environment variable is correctly configured.",
            file=sys.stderr,
        )
        sys.exit(11)
    with open(path) as file_:
        template = jinja2.Template(file_.read())
    """

    if not deployment_daemon and not command:
        print(
            """
            Try 'rtctkDeploymentGen job --help' for help.

    	    Error: Missing argument 'COMMAND'.
            """,
            file=sys.stderr,
        )
        exit(13)

    if deployment_daemon and command:
        print(
            "WARNING: When option '--deployment-daemon' is specified no need to specify 'COMMAND'",
            file=sys.stderr,
        )

    if isinstance(arguments, tuple) or isinstance(arguments, list):
        processed_arguments = " ".join(arguments)
    else:
        processed_arguments = arguments
    if "--cid" in processed_arguments:
        print(
            "ERROR: It is not allowed to provide --cid argument!",
            file=sys.stderr,
        )
        exit(11)

    if "--sde" in processed_arguments:
        msg = (
            "ERROR: It is not allowed to provide --sde argument."
            " The value for --sde is taken from --sde option!"
        )
        print(msg, file=sys.stderr)
        exit(12)

    kwargs = {}
    kwargs["depl"] = {}
    kwargs["depl"]["name"] = component_name
    kwargs["depl"]["user"] = ctx.user
    kwargs["depl"]["node"] = ctx.node
    if deployment_daemon:
        kwargs["depl"]["executable"] = "rtctkDeploymentDaemon"
    else:
        kwargs["depl"]["executable"] = command
    kwargs["depl"]["arguments"] = processed_arguments
    kwargs["depl"]["deployment_daemon"] = deployment_daemon
    kwargs["global"] = {}
    kwargs["global"]["datacenter"] = ctx.datacenter
    kwargs["global"]["app_kill_timeout"] = ctx.app_kill_timeout
    kwargs["global"]["sde"] = ctx.sde
    kwargs["global"]["no_services"] = no_services

    generate_nomad_job("rtctk_component", stdout=ctx.stdout, **kwargs)


@main.command()
@click.argument(
    "psr",
    type=UriParamType(),
)
@click.argument(
    "dp_path",
    type=DpPathParamType(),
)
@click.argument("global_path", type=DpPathParamType(), required=False)
@click.pass_obj
def job_from_psr(ctx, psr: Uri, dp_path, global_path):
    """Generate a nomad job file for c component from deployment information
    from Persistent Repository (PSR). Mainly to be used for testing.

    This program requires as input:

    - PSR: Location of the Persistent Repository as an URI.

    - DP_PATH: Path to component's deployment configuration in PSR.

    - [GLOBAL_PATH]: Path to global deployment configuration e.g. nomad in PSR.
    """

    kwargs = {}
    kwargs["depl"] = {}
    kwargs["depl"]["user"] = ctx.user
    kwargs["global"] = {}
    kwargs["global"]["datacenter"] = ctx.datacenter
    kwargs["global"]["app_kill_timeout"] = ctx.app_kill_timeout
    kwargs["global"]["sde"] = ctx.sde
    kwargs["global"]["no_services"] = True
    psr = PersistentRepoIf(psr)
    generate_nomad_job_from_dp(psr, dp_path, global_path, stdout=ctx.stdout, **kwargs)


@main.command()
@click.argument(
    "psr",
)
@click.argument(
    "oldb",
)
@click.argument("telegraf", required=False, default="null://null")
@click.option(
    "--as-consul-service",
    is_flag=True,
    default=False,
    help="Outputs instead a consul (.hcl) file with the RTCTK common service definition",
)
@click.pass_obj
def services(
    ctx,
    psr: str,
    oldb: str,
    telegraf: str,
    as_consul_service: bool,
):
    """Generate a nomad job file that provides the entries for Service Discovery.

    This sub-command requires two (optionally three) URIs as input:

    - PSR: Location of the Persistent Repository as a URI.

    - OLDB: Location of the OLDB as a URI.

    - TELEGRAF: (Optional) Location of the Telegraf endpoint as a URI.
    """
    extension = ""
    search_file = "unknown"
    try:
        if not as_consul_service:
            search_file = RTCTK_COMMON_SERVICE_NOMAD
            path = find_file(filepath=RTCTK_COMMON_SERVICE_NOMAD)
            extension = "nomad"
        else:
            search_file = RTCTK_COMMON_SERVICE_CONSUL
            path = find_file(filepath=RTCTK_COMMON_SERVICE_CONSUL)
            extension = "hcl"
    except Exception as e:
        print(e, file=sys.stderr)
        traceback.print_exc()
        sys.exit(10)
    if not os.path.isfile(path):
        print(
            f"Could not find file: {search_file}. Please make sure the RTC Toolkit is installed"
            " correctly and that the CFGPATH environment variable is correctly configured.",
            file=sys.stderr,
        )
        sys.exit(11)

    with open(path) as file_:
        template = jinja2.Template(file_.read())
    content = template.render(
        template_psr=psr,
        template_oldb=oldb,
        template_telegraf=telegraf,
        template_node=ctx.node,
        template_datacenter=ctx.datacenter,
    )
    if not ctx.stdout:
        with open(f"rtc_discovery_service.{extension}", "w") as output:
            output.write(content)
    else:
        print(content)


if __name__ == "__main__":
    main()  # pylint: disable=E1120
