# Copyright 2026 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.
import asyncio
import dataclasses
import os
import tempfile

import async_utils.command as command
from fx_cmd.lib import FxCmd
import statusinfo

import args
import environment
import event
import execution


async def get_diff_base(recorder: event.EventRecorder | None = None) -> str:
    """Determines the base commit for diffing, aligning with fx format-code."""
    upstream_res = await execution.run_command(
        "git",
        "rev-parse",
        "--abbrev-ref",
        "--symbolic-full-name",
        "@{u}",
        recorder=recorder,
    )
    upstream = ""
    if upstream_res and upstream_res.return_code == 0 and upstream_res.stdout:
        upstream = upstream_res.stdout.strip()

    if not upstream:
        ancestor_res = await execution.run_command(
            "git",
            "merge-base",
            "--is-ancestor",
            "origin/main",
            "HEAD",
            recorder=recorder,
        )
        if ancestor_res and ancestor_res.return_code == 0:
            upstream = "origin/main"
        else:
            ancestor_res = await execution.run_command(
                "git",
                "merge-base",
                "--is-ancestor",
                "JIRI_HEAD",
                "HEAD",
                recorder=recorder,
            )
            if ancestor_res and ancestor_res.return_code == 0:
                ancestor_res2 = await execution.run_command(
                    "git",
                    "merge-base",
                    "--is-ancestor",
                    "JIRI_HEAD",
                    "origin/main",
                    recorder=recorder,
                )
                if ancestor_res2 and ancestor_res2.return_code == 0:
                    mb_res = await execution.run_command(
                        "git",
                        "merge-base",
                        "HEAD",
                        "origin/main",
                        recorder=recorder,
                    )
                    if mb_res and mb_res.return_code == 0 and mb_res.stdout:
                        upstream = mb_res.stdout.strip()
                else:
                    upstream = "JIRI_HEAD"
            else:
                upstream = "HEAD"

    if upstream == "HEAD":
        return "HEAD"

    rev_list_res = await execution.run_command(
        "git",
        "rev-list",
        "HEAD",
        f"^{upstream}",
        "--",
        recorder=recorder,
    )

    if (
        not rev_list_res
        or rev_list_res.return_code != 0
        or not rev_list_res.stdout
    ):
        return "HEAD"

    lines = rev_list_res.stdout.splitlines()
    if not lines:
        return "HEAD"

    local_commit = lines[-1].strip()

    parent_res = await execution.run_command(
        "git",
        "rev-parse",
        f"{local_commit}^",
        recorder=recorder,
    )

    if parent_res and parent_res.return_code == 0 and parent_res.stdout:
        return parent_res.stdout.strip()

    return "HEAD"


async def get_dirty_files(
    fuchsia_dir: str,
    affected_since: str | None = None,
    recorder: event.EventRecorder | None = None,
) -> list[str] | None:
    """Invokes git to identify modified files.

    Args:
        fuchsia_dir: The Fuchsia directory.
        affected_since: If set, compare against this commit/branch instead of checking uncommitted files.
        recorder: The event recorder.

    Returns:
        A list of modified files relative to fuchsia_dir, or None if clean/invalid.
    """
    toplevel_res = await execution.run_command(
        "git",
        "rev-parse",
        "--show-toplevel",
        recorder=recorder,
    )
    if not toplevel_res or toplevel_res.return_code != 0:
        if recorder:
            stdout = toplevel_res.stdout if toplevel_res else "None"
            stderr = toplevel_res.stderr if toplevel_res else "None"
            recorder.emit_instruction_message(
                "ERROR: You must run fx test from inside a git repository to use --show-affected-tests.\n"
                f"STDOUT: {stdout}\n"
                f"STDERR: {stderr}"
            )
        return None

    repo_root = toplevel_res.stdout.strip() if toplevel_res.stdout else ""
    if recorder:
        recorder.emit_instruction_message(f"Querying repository: {repo_root}")

    dirty_files = []
    diff_base = affected_since
    if not diff_base:
        diff_base = await get_diff_base(recorder)

    if recorder:
        recorder.emit_instruction_message(
            f"Querying files changed since {diff_base}"
        )

    diff_args = ["git", "diff", "--name-only", diff_base]

    diff_res = await execution.run_command(
        *diff_args,
        recorder=recorder,
    )

    if not diff_res or diff_res.return_code != 0 or diff_res.stdout is None:
        if recorder:
            stdout = diff_res.stdout if diff_res else "None"
            stderr = diff_res.stderr if diff_res else "None"
            recorder.emit_warning_message(
                f"Failed to run git diff against {diff_base}\n"
                f"STDOUT: {stdout}\n"
                f"STDERR: {stderr}"
            )
        return None

    for line in diff_res.stdout.splitlines():
        rel_path = line.strip()
        if not rel_path:
            continue
        abs_path = os.path.join(repo_root, rel_path)
        dirty_files.append(os.path.relpath(abs_path, fuchsia_dir))

    if not dirty_files:
        msg = (
            f"\nNo files changed since {affected_since}."
            if affected_since
            else "\nYour repository is completely clean. No files are modified, so no tests are affected."
        )
        if recorder:
            recorder.emit_instruction_message(msg)
        return None

    return dirty_files


@dataclasses.dataclass(frozen=True)
class BuildConfig:
    """Represents a product/board configuration for finding affected tests."""

    product_board: str
    with_args: list[str]


@dataclasses.dataclass(frozen=True)
class AffectedResult:
    """Represents a single affected test target result from the build API."""

    label: str
    is_host: bool


@dataclasses.dataclass(frozen=True)
class GatheredResult:
    """Represents the set of affected tests for a specific build configuration."""

    product_board: str
    affected_results: list[AffectedResult]


@dataclasses.dataclass(frozen=True)
class FormattedResult:
    """Represents the aggregated configuration info for a specific test label."""

    is_host: bool
    pb_configs: list[str]


@dataclasses.dataclass(frozen=True)
class AffectedTarget:
    """Represents a matched affected test target formatted for display."""

    pure_label: str
    pb_configs: list[str]
    command: str


def format_affected_targets(
    label_to_results: dict[str, FormattedResult]
) -> list[AffectedTarget]:
    """Sorts and formats affected targets into their respective commands."""
    results = []
    for label, res in sorted(label_to_results.items()):
        pure_label = label.split("(")[0]
        if res.is_host:
            cmd = f"fx add-host-test {pure_label}"
        else:
            cmd = f"fx add-test {pure_label}"
        results.append(AffectedTarget(pure_label, res.pb_configs, cmd))
    return results


def clean_gathered_results(
    results: list[GatheredResult],
) -> dict[str, FormattedResult]:
    """Maps explicitly affected test GN labels back to configured board products."""
    label_to_results: dict[str, FormattedResult] = {}
    for res in results:
        pb = res.product_board
        for affected in res.affected_results:
            label = affected.label
            is_host = affected.is_host
            if not label or not label.startswith(("//", "@")):
                continue
            if label not in label_to_results:
                label_to_results[label] = FormattedResult(is_host, [])
            # Append configs
            if pb not in label_to_results[label].pb_configs:
                label_to_results[label].pb_configs.append(pb)
    return label_to_results


def parse_build_api_output(
    out_client: command.CommandOutput | None,
) -> list[AffectedResult]:
    """Parses the output from build/api/client affected_tests.

    Returns:
        A list of AffectedResult objects.
    """
    if not out_client or out_client.return_code != 0:
        return []

    out_text = out_client.stdout.strip() if out_client.stdout else ""
    parsed_results = []
    for line in out_text.splitlines():
        line = line.strip()
        if not line:
            continue
        parts = line.split(",")
        if len(parts) >= 2:
            parsed_results.append(AffectedResult(parts[0], parts[1] == "host"))
        else:
            parsed_results.append(AffectedResult(parts[0], False))
    return parsed_results


async def find_affected_tests(
    fuchsia_dir: str,
    product_board: str,
    out_dir: str,
    with_args: list[str],
    files_list: str,
) -> GatheredResult:
    """Configures a temporary build graph and finds affected tests using build-api-client.

    Returns:
        A GatheredResult object containing board info and affected test list.
    """
    fx = FxCmd(build_directory=out_dir)
    set_args = [
        "set",
        product_board,
        "--no-change-env",
        "--rbe-mode=off",
    ]
    for w in with_args:
        set_args.extend(["--with", w])

    try:
        running_fx = await fx.start(*set_args)
        out_set = await running_fx.run_to_completion()
        if out_set.return_code != 0:
            return GatheredResult(product_board, [])

        client_cmd = [
            f"{fuchsia_dir}/build/api/client",
            "--build-dir",
            out_dir,
            "affected_tests",
            f"--files-list={files_list}",
        ]

        out_client = await execution.run_command(
            *client_cmd,
        )

        return GatheredResult(product_board, parse_build_api_output(out_client))

    except Exception:
        return GatheredResult(product_board, [])


async def get_affected_targets(
    exec_env: environment.ExecutionEnvironment,
    affected_since: str | None = None,
    recorder: event.EventRecorder | None = None,
) -> list[AffectedTarget]:
    """Orchestrates discovering which tests are affected by dirty files across several different configurations."""

    dirty_files = await get_dirty_files(
        exec_env.fuchsia_dir, affected_since, recorder
    )
    if dirty_files is None:
        return []

    if recorder:
        recorder.emit_instruction_message(
            f"Found {len(dirty_files)} modified file(s)."
        )

    with tempfile.NamedTemporaryFile(
        mode="w", suffix=".txt", delete=True
    ) as dirty_files_file:
        dirty_files_file.write("\n".join(dirty_files) + "\n")
        # Ensure it's fully flushed to disk!
        dirty_files_file.flush()
        dirty_files_path = dirty_files_file.name

        with tempfile.TemporaryDirectory(dir=exec_env.out_dir) as out_tmp_dir:
            build_configurations = [
                BuildConfig("core.x64", ["//bundles/buildbot/core"]),
                BuildConfig("core.arm64", ["//bundles/buildbot/core"]),
                BuildConfig("minimal.x64", ["//bundles/buildbot/minimal"]),
                BuildConfig("minimal.arm64", ["//bundles/buildbot/minimal"]),
                BuildConfig(
                    "bringup_with_tests.x64", ["//bundles/buildbot/bringup"]
                ),
                BuildConfig(
                    "bringup_with_tests.arm64", ["//bundles/buildbot/bringup"]
                ),
            ]

            group_id = None
            if recorder:
                group_id = recorder.emit_event_group(
                    "Finding affected tests",
                    queued_events=len(build_configurations),
                )

            async def run_find_affected(
                config: BuildConfig,
            ) -> GatheredResult:
                child_id = None
                if recorder:
                    child_id = recorder.emit_event_group(
                        f"Checking {config.product_board}", parent=group_id
                    )
                try:
                    pb_slug = config.product_board.replace(".", "_")
                    out_dir = os.path.join(out_tmp_dir, pb_slug)

                    return await find_affected_tests(
                        exec_env.fuchsia_dir,
                        config.product_board,
                        out_dir,
                        config.with_args,
                        dirty_files_path,
                    )
                finally:
                    if recorder and child_id:
                        recorder.emit_end(id=child_id)

            if recorder:
                recorder.emit_instruction_message(
                    f"Spawning parallel evaluations for {len(build_configurations)} product/board configurations (this might take a minute)..."
                )

            try:
                results = await asyncio.gather(
                    *(
                        run_find_affected(config)
                        for config in build_configurations
                    )
                )
            finally:
                if recorder and group_id:
                    recorder.emit_end(id=group_id)

            label_to_results = clean_gathered_results(results)
            if not label_to_results:
                return []

            return format_affected_targets(label_to_results)


async def show_affected_tests(
    exec_env: environment.ExecutionEnvironment,
    flags: args.Flags,
    recorder: event.EventRecorder,
) -> None:
    """Orchestrates discovering which tests are affected by dirty files across several different configurations."""
    targets = await get_affected_targets(
        exec_env, flags.affected_since, recorder
    )

    if not targets:
        recorder.emit_info_message(
            "\nNone of your modified files affect any known tests across the 6 major configurations."
        )
        return

    recorder.emit_info_message(
        f"\nFound {len(targets)} affected test(s) matching your uncommitted files:\n"
    )

    for target in targets:
        recorder.emit_verbatim_message(
            f"{statusinfo.highlight(target.pure_label, style=flags.style)} ({', '.join(target.pb_configs)})"
        )

        dim_cmd = statusinfo.dim(f"  > {target.command}", style=flags.style)
        recorder.emit_verbatim_message(dim_cmd)
