# Copyright 2025 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Helper classes to deal with @gn_targets dependencies in the Fuchsia workspace."""

import dataclasses
import json
import subprocess
import sys
import typing as T
from pathlib import Path


@dataclasses.dataclass
class BazelBuildActionInfo(object):
    """Model an entry in the bazel_build_action_targets.json file.

    See //BUILD.gn for schema description.
    """

    # LINT.IfChange(bazel_build_actions)
    gn_target: str
    bazel_targets: list[str]
    no_sdk: bool
    gn_targets_dir: str
    gn_targets_manifest: str
    gn_targets_licenses_spdx: str
    debug_symbols_manifest: str
    bazel_command_file: str = ""
    bazel_compdb_file: str = ""
    path_mapping: str = ""
    timings_file: str = ""
    build_events_log_json: str = ""
    # LINT.ThenChange(//BUILD.gn:bazel_build_actions)


class BazelBuildActionsMap(object):
    """A class used to model a map of Bazel top-level targets to the GN bazel_action() labels that builds them.

    This is built from the content of the //:bazel_build_action_targets generated_file() output.
    This does not provide information about the dependencies of the top-level Bazel actions,
    for these, an actual Bazel query is needed, see BazelBuildActionQuery below.
    """

    def __init__(self, json_content: list[dict[str, T.Any]]) -> None:
        self._targets: dict[str, BazelBuildActionInfo] = {}
        self._bazel_to_gn: dict[str, str] = {}
        for entry in json_content:
            info = BazelBuildActionInfo(**entry)
            self._targets[info.gn_target] = info
            for bazel_target in info.bazel_targets:
                self._bazel_to_gn[bazel_target] = info.gn_target

    @staticmethod
    def FromBuildDir(build_dir: Path) -> "BazelBuildActionsMap":
        """Create instance from content of Ninja build directory.

        Args:
            build_dir: Ninja build directory, populated by `fx gen`.
        Returns:
            New BazelBuildActionsMap
        Raises:
            FileNotFoundError if file is missing.
        """
        with (build_dir / "bazel_build_action_targets.json").open("rb") as f:
            content = json.load(f)
        return BazelBuildActionsMap(content)

    @property
    def bazel_targets(self) -> list[str]:
        return sorted(self._bazel_to_gn.keys())

    @property
    def gn_targets(self) -> list[str]:
        return sorted(set(self._bazel_to_gn.values()))

    def get_info(self, gn_label: str) -> T.Optional[BazelBuildActionInfo]:
        """Retrieve BazelBuildActionInfo matching a given GN label."""
        return self._targets.get(gn_label)

    def find_gn_target_for(self, bazel_target: str) -> str:
        """Retrieve the GN target label used to build a given top-level Bazel target.

        Args:
            bazel_target: A top-level Bazel target that is built by one of
               the GN bazel_action() targets.

        Returns:
            The corresponding GN target label, or an empty string if there is no match.
        """
        return self._bazel_to_gn.get(bazel_target, "")


class BazelBuildActionQuery(object):
    """Convenience class to wrap Bazel query operations when trying to find
    the wrapping GN bazel_action() target for a given Bazel target.
          GN target, or in case of failure, a message explaining its reason.
    """

    def __init__(
        self, bazel_target: str, actions_map: BazelBuildActionsMap
    ) -> None:
        """Create instance."""
        self._bazel_target = bazel_target
        self._actions_map = actions_map

    def make_query_command(self, bazel_pre_cmd_args: list[str]) -> list[str]:
        """Return the query command to be performed.

        Note that this forces @gn_targets to be empty, which will generate errors
        that are ignored through the use of --keep_going. The error output *must*
        be filtered with filter_query_errors() to detect real errors, before
        calling process_query_output().

        Args:
            bazel_pre_cmd_args: List of command-line arguments that appear before the 'query'
               command. At a minimum, this would be a list with a single item with the path
               of the Bazel binary / launcher script.
        Returns:
            A string list representing a command to be passed to a function
            like subprocess.run().
        """
        query_expr = "allpaths(set(%s), %s)" % (
            " ".join(self._actions_map.bazel_targets),
            self._bazel_target,
        )

        return bazel_pre_cmd_args + [
            "query",
            "--config=no_gn_targets",
            "--config=quiet",
            "--keep_going",
            query_expr,
        ]

    @staticmethod
    def filter_query_errors(errors: str) -> str:
        """Filter the errors generated by the invocation of a make_query_command() result.

        This removes all errors that are due to the empty @gn_targets repository,
        but leaves any others, to catch unexpected breakages due to developer changes.

        Args:
            errors: The query's command stderr output as a string.
        Returns:
            The error output without expected errors related to  @gn_targets.
            A non-empty value means that real errors were detected during the query.
        """
        real_errors = []
        for error in errors.splitlines():
            if (
                error.startswith("ERROR: ")
                and "no such package '@@gn_targets//" in error
            ):
                continue
            if error.startswith(
                "Starting local Bazel server and connecting to it..."
            ):
                continue
            if error.startswith('ERROR: Evaluation of query "allpaths(set('):
                continue
            if error.startswith(
                "WARNING: --keep_going specified, ignoring errors."
            ):
                continue
            real_errors.append(error)

        return "\n".join(real_errors)

    def process_query_output(self, query_result: str) -> list[str]:
        """Parse the result of a Bazel query to get a list of GN  bazel_action() labels.

        Args:
            query_result: The stdout of running the Bazel cquery command generated
                by make_query_command() as a string.
        Returns:
            A list of GN target strings, each pointing to a target definition
            using bazel_action() or one of its wrappers, that depend on this
            instance's bazel target.
        """
        lines = query_result.splitlines()
        gn_targets = set()

        for line in lines:
            gn_target = self._actions_map.find_gn_target_for(line)
            if gn_target:
                gn_targets.add(gn_target)

        return sorted(gn_targets)


# A LogSinkType models a callable that takes an log message and returns None.
LogSinkType: T.TypeAlias = T.Callable[[str], None]


def _stderr_log_sink(msg: str) -> None:
    print(msg, file=sys.stderr)


# A CommandRunnerType is a callable that takes a list of command strings,
# and returns a (returncode, stdout, stderr) tuple from its execution.
CommandRunnerType: T.TypeAlias = T.Callable[[list[str]], tuple[int, str, str]]


def _subprocess_command_runner(args: list[str]) -> tuple[int, str, str]:
    """A CommandRunnerType implementation that uses subprocess.run()."""
    ret = subprocess.run(
        args, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
    )
    return ret.returncode, ret.stdout, ret.stderr


def find_gn_bazel_action_infos_for(
    bazel_target: str,
    actions_map: BazelBuildActionsMap,
    bazel_cmd_args: list[str],
    log_step: T.Optional[LogSinkType] = None,
    log_err: LogSinkType = _stderr_log_sink,
    command_runner: CommandRunnerType = _subprocess_command_runner,
) -> list[BazelBuildActionInfo]:
    """Find the BazelBuildActionInfo instances matching a given Bazel target.

    Find all GN bazel_action() target whose top-level bazel targets
    depend on a given |bazel_target|, and return the corresponding
    BazelBuildActionInfo items in a list.

    This is the main logic around `fx bazel-tool set_gn_targets`.

    Args:
        bazel_target: Bazel target label to look for. Must start
           with // or @.

        actions_map: A BazelBuildActionsMap instance used as input.

        bazel_cmd_args: A list of strings making up a command-line
           invocation for Bazel, before the "query" command.
           E.g.: ["bazel"]

        log_step: An optional LogSink callable used to print log messages.

        log_err: An optional LogSink callable used to send error messages.
           Defaults to _stderr_log_sink which simply sends errors to
           sys.stderr.

        command_runner: An optional CommandRunner to run the final
           Bazel query command. Defaults to _subprocess_command_runner
           that uses subprocess.run.

    Returns:
        A list of BazelBuildActionInfo items. In case of failure,
        errors will be sent to |log_err| and the function will return
        an empty list.

        An empty list without errors means the target is not a known
        dependency of the actions_map's GN and Bazel targets.

    Raises:
        AssertionError if |bazel_target| has invalid format.
    """
    # Check inputs.
    if not bazel_target.startswith(("@", "//")):
        log_err(f"Target label must start with // or @: {bazel_target}")
        return []

    if "(" in bazel_target:
        log_err(
            f"Target label cannot include GN toolchain suffix: {bazel_target}"
        )
        return []

    gn_target = actions_map.find_gn_target_for(bazel_target)
    if gn_target:
        if log_step:
            log_step(
                f"Bazel target {bazel_target} maps directly to GN target {gn_target}"
            )
        info = actions_map.get_info(gn_target)
        assert info  # Appease mypy
        return [info]

    action_query = BazelBuildActionQuery(bazel_target, actions_map)
    query_command = action_query.make_query_command(bazel_cmd_args)
    returncode, stdout, stderr = command_runner(query_command)
    if returncode != 0:
        stderr = action_query.filter_query_errors(stderr)
        if stderr:
            # Report unexpected errors directly.
            log_err(f"Bazel query returned unexpected errors:\n%s\n" % stderr)
            return []

    gn_targets = action_query.process_query_output(stdout)

    if log_step:
        log_step(f"Bazel query result: {gn_targets}")

    result = []
    for gn_target in gn_targets:
        info = actions_map.get_info(gn_target)
        assert info  # Appease mypy
        result.append(info)

    return result
