#!/usr/bin/python3
"""
Support routines for dh-fortran cli commands

Copyright (C) 2025 Alastair McKinstry <mckinstry@debian.org>
Released under the GPL-3 Gnu Public License.
"""

import dhfortran.compilers as cmplrs
import traceback
import click
import os
import sys
import subprocess
import logging
import json

log = logging.getLogger("dhfortran")

verbose = None
debug = False


def is_multifortran_build():
    d = cmplrs.get_fc_required()
    o = cmplrs.get_fc_optional()
    return len(d) + len(o) > 1


def verbose_print(s: str):
    log.debug(s)
    global verbose
    if verbose is None:
        verbose = os.environ['DH_VERBOSE'] if 'DH_VERBOSE' in os.environ else False
    if verbose:
        click.echo(s)


def debug_print(s: str):
    log.debug(s)
    global debug
    if debug:
        click.echo(s)


def warning(s: str):
    log.warning(s)
    click.echo(s, err=True)


def update_env(kwargs):
    """Helper: on intercept, ensure present and set:
    buildsystem : 'active' buildsytem to use
    tmpdir : to install into.
    builddir : builddir. to build into.
    """
    try:
        j = subprocess.check_output(["dh_assistant", "which-build-system"])
    except subprocess.CalledProcessError:
        print("Error: must be run inside a package source directory")
        sys.exit(1)

    d = json.loads(j.decode("utf-8"))

    if "builddir" not in kwargs or kwargs["builddir"] is None:
        kwargs["builddir"] = d["buildpath"]
    if kwargs["builddir"] == ".":
        if cmplrs.is_multifortran_build():
            kwargs["builddir"] = "debian/build"
    # TODO needed?
    # kwargs['o__builddirectory'] = kwargs['builddir']

    # TODO: Handle the case of '--var','value' as well ?
    if "tmpdir" not in kwargs:
        for arg in sys.argv:
            if arg.startswith("-O--tmpdir="):
                kwargs["tmpdir"] = arg[11:]
    if "tmpdir" not in kwargs:
        kwargs["tmpdir"] = d["dest-directory"]
    if kwargs["tmpdir"] is None:
        kwargs["tmpdir"] = "debian/tmp"

    # Note: 'buildystem' is distinct from 'o__buildsystem'
    # 'buildsystem' comes from --with= (eg. fortran, ecbuild)
    # 'o__buildsystem' may be eg meson+ninja, cmake+makefile
    # TODO: test dropping setting of o__buildsystem
    kwargs["o__buildsystem"] = d["build-system"]
    if "buildsystem" not in kwargs:
        for arg in sys.argv:
            if arg.startswith("-O--buildsystem="):
                kwargs["buildsystem"] = arg[16:]
    if "buildsystem" not in kwargs or kwargs["buildsystem"] is None:
        kwargs["buildsystem"] = kwargs["o__buildsystem"]
    # Replace 'ecbuild' with underlying system
    if kwargs["buildsystem"] == "ecbuild":
        kwargs["buildsystem"] = kwargs["o__buildsystem"]

    assert kwargs["buildsystem"] is not None
    assert "tmpdir" in kwargs
    assert "builddir" in kwargs

    return kwargs


# decorator
def debhelper_common_args(f, minimal=False):
    """This is a wrapper that is the the top-level entry point to dh-fortran commands.
    Validation of arguments, env variables happens here
    """

    # Wrapper to add debhelper common args to all targets
    @click.option(
        "--verbose",
        "-v",
        help="show commands that modify the package build directory",
        is_flag=True,
    )
    @click.option(
        "--tmpdir",
        "-P",
        help="Use  tmpdir for package build staging directory",
    )
    @click.option("--destdir", help="Use destdir as the destination for final install")
    @click.option(
        "--sourcedir",
        "--sourcedirectory",
        "-D",
        envvar="SOURCEDIR",
        default=".",
        hidden=True,
    )
    @click.option("--builddir", "--builddirectory", "-B", help="Build directory")
    # Ignore the following parameters
    @click.option("-O--no-parallel", is_flag=True, hidden=True)
    @click.option("-O--buildsystem", "--buildsystem", "-S", hidden=True)
    @click.option("-O--builddirectory", "-O--builddir", "-O", hidden=True)
    def wrapper(*args, **kwargs):

        global verbose, debug
        if "DH_VERBOSE" in os.environ:
            verbose = os.environ["DH_VERBOSE"]
        else:
            verbose = kwargs["verbose"] if "verbose" in kwargs else False
        if "DH_DEBUG" in os.environ and os.environ["DH_DEBUG"]:
            debug = True
            verbose = True

        kwargs = update_env(kwargs)

        try:
            f(*args, **kwargs)
        except Exception as ex:
            if verbose:
                print(traceback.format_exc())
            raise click.UsageError(ex)

    if not minimal:
        # Options that don't apply to dh_fortran helpers, just dh_fortran_*
        wrapper = click.option(
            "--no-act", help="Don't act, just show the output", is_flag=True
        )(wrapper)
        wrapper = click.option("--package", "-p", help="Act on named package")(wrapper)
        wrapper = click.option("--firstpackage", envvar="FIRSTPACKAGE", hidden=True)(
            wrapper
        )
        wrapper = click.option(
            "--indep",
            "-i",
            help="Act on all arch-independent packages",
            is_flag=True,
        )(wrapper)
        wrapper = click.option(
            "--arch", "-a", help="Act on all arch-dependent packages", is_flag=True
        )(wrapper)
        wrapper = click.option(
            "--remaining-packages",
            help="Act on remaining packages only",
            hidden=True,
        )(wrapper)
        wrapper = click.option(
            "--no-package",
            "-N",
            help="Do  not act on the specified package",
            hidden=True,
        )(wrapper)
        wrapper = click.option(
            "--mainpackage", help="Deprecated and unused", hidden=True
        )(wrapper)
        wrapper = click.option("--create-in-sourcedir", hidden=True)(wrapper)
        wrapper = click.option(
            "--exclude_pkgs",
            "-X",
            help="Exclude certain packages",
            envvar="EXCLUDE_FIND",
            hidden=True,
        )(wrapper)

    return wrapper


def validate_flavor(flavor: str) -> None:
    # Validation moved get_fc_flavor_arch does checking
    try:
        flavor, arch = cmplrs.get_fc_flavor_arch(flavor)
    except Exception as ex:
        raise click.UsageError(ex)


def validate_compiler(fc: str) -> None:
    # Validation moved; get_fc_flavor does checking
    try:
        flavor, arch = cmplrs.get_fc_flavor_arch(fc)
    except Exception as ex:
        raise click.UsageError(ex)


if __name__ == "__main__":
    import pytest

    pytest.main(["tests/cli.py"])
