# Copyright 2023 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 ipaddress
import math
import os
import re
import tempfile
import typing

_MOBLY_CLASS_HEADER_REGEX = re.compile(
    r"^==========> (?P<class_name>.*) <==========$"
)

_MOBLY_TEST_OUTPUT_TEMPLATE = (
    'fx test --e2e {test_name} -- --test_cases="{test_case}"'
)

_PYTHON_HOST_TEST_OUTPUT_TEMPLATE = 'fx test {test_name} -- -k "{test_case}"'

_DEFAULT_TEST_OUTPUT_TEMPLATE = (
    'fx test {test_name} --test-filter "{test_case}"'
)

import async_utils.command as command
import statusinfo

import args
import environment
import event
import package_repository
import test_list_file

# The timeout command-line argument can be used to specify a timeout for all tests that are run
# in a given invocation of 'fx 'test'. The default behavior is to use the 'normal' timeout value
# for each test. A few tests have specific 'normal' timeout values specified using test_spec
# values in build files, but most tests use this default timeout of 5 minutes.
DEFAULT_TIMEOUT = 5 * 60

# Bounded timeout for target device discovery, address resolution, and ssh key lookups.
_DEVICE_PROBE_TIMEOUT_SECONDS: float = 30.0


class TestExecutionError(Exception):
    """Base error type for test failures."""

    def __init__(self, message: str, command_output: typing.Any = None):
        super().__init__(message)
        self.command_output = command_output


class TestCouldNotRun(TestExecutionError):
    """The test could not be run at all."""


class TestSkipped(TestExecutionError):
    """The test was skipped for some non-error reason"""


class TestFailed(TestExecutionError):
    """The test ran, but returned a failure error code."""


class TestTimeout(TestExecutionError):
    """The test timed out."""


# Unique number suffix for output subdirectories.
UNIQUE_OUTPUT_SUFFIX = 0


class TestExecution:
    """Represents a single execution for a specific test."""

    def __init__(
        self,
        test: test_list_file.Test,
        exec_env: environment.ExecutionEnvironment,
        flags: args.Flags,
        run_suffix: int | None = None,
        device_env: environment.DeviceEnvironment | None = None,
    ):
        """Initialize the test execution wrapper.

        Args:
            test (test_list_file.Test): Test to run.
            exec_env (environment.ExecutionEnvironment): Execution environment.
            flags (args.Flags): Command flags.
            run_suffix (int, optional): If set, this is the unique
                index of a single run of the referenced test.
            device_env (environment.DeviceEnvironment, optional):
                If set, this contains information on how to connect to
                a device. Otherwise if this is a host test it may not
                connect to a device.
        """
        global UNIQUE_OUTPUT_SUFFIX
        self._test = test
        self._exec_env = exec_env
        self._flags = flags
        self._run_suffix = run_suffix
        self._device_env = device_env
        if self._flags.artifact_output_directory is not None:
            self._outdir: str | None = os.path.join(
                self._flags.artifact_output_directory, str(UNIQUE_OUTPUT_SUFFIX)
            )
            UNIQUE_OUTPUT_SUFFIX += 1
        else:
            self._outdir = None

    def name(self) -> str:
        """Get the name of the test.

        Returns:
            str: Name of the test.
        """
        return self._test.name() + (
            f" (Run {self._run_suffix})" if self._run_suffix is not None else ""
        )

    def is_hermetic(self) -> bool:
        """Determine if a test is hermetic.

        Returns:
            bool: True if the wrapped test is hermetic, False otherwise.
        """
        return self._test.info.is_hermetic()

    def is_host_test(self) -> bool:
        """Determine if a test is a pure host test.

        Returns:
            bool: True if the wrapped test is a pure host test, False otherwise.
        """
        return bool(self._test.is_host_test())

    def command_line(self, test_cases: list[str] | None = None) -> list[str]:
        """Format the command line required to execute this test.

        Raises:
            TestCouldNotRun: If we do not know how to run this type of test.

        Returns:
            list[str]: The command line for the test.
        """

        min_severity_logs: list[str] = []

        if self._use_test_pilot() and self._test.info.execution is not None:
            # assert for mypy
            assert self._test.build.test.new_path is not None

            execution = self._test.info.execution

            if self._flags.min_severity_logs:
                min_severity_logs = self._flags.min_severity_logs
            elif execution.min_severity_logs is not None:
                min_severity_logs = [execution.min_severity_logs]

            extra_args = []

            if execution.realm:
                extra_args += ["--realm=" + execution.realm]
            if execution.max_severity_logs and self._flags.restrict_logs:
                extra_args += [
                    "--max-severity-logs=" + execution.max_severity_logs,
                ]
            if min_severity_logs:
                extra_args += [
                    "--min-severity-logs=" + ",".join(min_severity_logs)
                ]

            parallel_cases = self._flags.parallel_cases
            if (
                parallel_cases == 0
                and self._test.build.test.parallel is not None
            ):
                parallel_cases = self._test.build.test.parallel
            if parallel_cases != 0:
                extra_args += [
                    "--max-concurrent-test-case-runs=" + str(parallel_cases),
                ]

            for test_filter in self._flags.test_filter:
                extra_args += ["--test-case-filter=" + test_filter]
            if self._flags.also_run_disabled_tests:
                extra_args += ["--run-disabled-cases"]
            if self._flags.show_full_moniker_in_logs:
                extra_args += ["--show-full-moniker-in-logs"]
            if self._flags.break_on_failure:
                extra_args += ["--break-on-failure"]

            if self._flags.extra_args:
                extra_args += [
                    "--target-test-args=" + ",".join(self._flags.extra_args)
                ]

            timeout = self._calculate_timeout()
            if timeout is not None:
                extra_args += [
                    "--timeout=" + str(math.ceil(timeout)),
                ]

            return [
                os.path.join(
                    self._exec_env.out_dir, self._test.build.test.new_path
                )
            ] + extra_args

        elif self._test.info.execution is not None:
            exec_env = self._exec_env
            execution = self._test.info.execution

            component_url = self._get_component_url()
            assert component_url is not None

            if self._flags.min_severity_logs:
                min_severity_logs = self._flags.min_severity_logs
            elif execution.min_severity_logs is not None:
                min_severity_logs = [execution.min_severity_logs]

            extra_args = []
            if execution.realm:
                extra_args += ["--realm", execution.realm]
            if execution.max_severity_logs and self._flags.restrict_logs:
                extra_args += [
                    "--max-severity-logs",
                    execution.max_severity_logs,
                ]
            if min_severity_logs:
                for min_severity_log in min_severity_logs:
                    extra_args += ["--min-severity-logs", min_severity_log]

            parallel_cases = self._flags.parallel_cases
            if (
                parallel_cases == 0
                and self._test.build.test.parallel is not None
            ):
                parallel_cases = self._test.build.test.parallel
            if parallel_cases != 0:
                extra_args += [
                    "--parallel",
                    str(parallel_cases),
                ]

            if (
                self._test.build.test.create_no_exception_channel is not None
                and self._test.build.test.create_no_exception_channel
            ):
                extra_args += [
                    "--no-exception-channel",
                ]

            # If command line filters are given, they should override (cancel)
            # any filters that may be in test-list.json.
            test_execution_filters = self._test.info.execution.test_filters
            if self._flags.test_filter:
                for test_filter in self._flags.test_filter:
                    extra_args += ["--test-filter", test_filter]
            elif test_execution_filters:
                extra_args.append("--no-cases-equals-success")
                for test_filter in test_execution_filters:
                    extra_args += ["--test-filter", test_filter]
            if self._flags.also_run_disabled_tests:
                extra_args += ["--run-disabled"]
            if self._flags.show_full_moniker_in_logs:
                extra_args += ["--show-full-moniker-in-logs"]
            if self._flags.break_on_failure:
                extra_args += ["--break-on-failure"]
            if self._outdir is not None:
                extra_args += ["--output-directory", self._outdir]
            if self._flags.capture_syslog:
                extra_args += ["--capture-syslog"]

            timeout = self._calculate_timeout()
            if timeout is not None:
                extra_args += [
                    "--timeout",
                    str(math.ceil(timeout)),
                ]

            suffix_args = (
                ["--"] + self._flags.extra_args
                if self._flags.extra_args
                else []
            )

            return (
                exec_env.fx_cmd_line("ffx", "test", "run")
                + extra_args
                + [component_url]
                + suffix_args
            )
        elif self._test.build.test.path:
            command_line = [self._test.build.test.path]
            if self._test.is_e2e_test() and self._device_env is not None:
                if (
                    self._test.build.test.list_cases_argument
                    == "list_mobly_tests"
                ):
                    command_line += [
                        "--ssh-key",
                        self._device_env.private_key_path,
                    ]
            if test_cases:
                command_line += ["--test_cases"] + test_cases
            return command_line + self._flags.extra_args
        else:
            raise TestCouldNotRun(
                f"We do not know how to run this test: {str(self._test)}"
            )

    def enumerate_cases_command_line(self) -> list[str] | None:
        """Get the command line to enumerate all test cases in this test.

        If this type of test does not support test case enumeration,
        return None.

        Returns:
            list[str] | None: Command line to enumerate cases
                if possible, None otherwise.
        """

        # If the test definition includes a `list_cases_argument` (e.g. "list_mobly_tests"),
        # we construct a command to execute the test binary with that argument.
        # This is primarily used for host tests which support listing cases via a flag.
        if (
            self._test.build.test.list_cases_argument
            and self._test.build.test.path
        ):
            arg = f"--{self._test.build.test.list_cases_argument}"
            path = self._test.build.test.path
            if not os.path.isabs(path):
                path = os.path.join(self._exec_env.out_dir, path)
            return [path, arg]

        execution = self._test.info.execution
        exec_env = self._exec_env

        try:
            component_url = self._get_component_url()
        except TestCouldNotRun:
            return None
        if component_url is None or execution is None:
            return None

        extra_args = []
        if execution.realm:
            extra_args += ["--realm", execution.realm]

        return (
            exec_env.fx_cmd_line("ffx", "test", "list-cases")
            + extra_args
            + [component_url]
        )

    def enumerate_cases_output_template(self) -> str:
        """Get the template string for the output command.

        Returns:
            str: The template string
        """
        # TODO(fxbug.dev/481539525): This behavior should ideally be in a script run by fx test
        if self._test.build.test.list_cases_argument == "list_mobly_tests":
            return _MOBLY_TEST_OUTPUT_TEMPLATE
        if (
            self._test.build.test.list_cases_argument
            == "list_host_python_unittests"
        ):
            return _PYTHON_HOST_TEST_OUTPUT_TEMPLATE
        return _DEFAULT_TEST_OUTPUT_TEMPLATE

    async def enumerate_mobly_test(
        self,
        recorder: event.EventRecorder,
        parent: event.Id | None = None,
    ) -> command.CommandOutput | None:
        """Enumerate test cases for this (Mobly) test.

        Args:
            recorder (event.EventRecorder): Recorder for events.
            parent (event.Id | None): Parent event ID.

        Returns:
            command.CommandOutput | None: Command output if successful.
        """
        cmd = self.enumerate_cases_command_line()
        if not cmd:
            return None

        env = self.environment() or {}
        cwd = env.get("CWD")

        # mobly_driver (and potentially others) requires FUCHSIA_TEST_OUTDIR to be set.
        # We create a temporary directory for enumeration outputs.
        with tempfile.TemporaryDirectory() as temp_out_dir:
            # Adjust temp_out_dir if CWD is set, mirroring execution.py logic
            out_dir_val = temp_out_dir
            if cwd and not os.path.isabs(out_dir_val):
                out_dir_val = os.path.relpath(out_dir_val, cwd)

            env["FUCHSIA_TEST_OUTDIR"] = out_dir_val

            output = await run_command(
                *cmd,
                recorder=recorder,
                parent=parent,
                env=env,
                print_verbatim=False,
            )

            if output and output.stdout:
                # Parse Mobly output to extract test cases.
                # Format is:
                # ==========> ClassName <==========
                # test_name_1
                # test_name_2
                lines = output.stdout.splitlines()
                clean_lines = []

                # We discard all output lines until we match a class header.
                # Once a header is found, subsequent lines are treated as test case names
                # belonging to that class, until EOL.
                current_class = None
                for line in lines:
                    line = line.strip()
                    if not line:
                        continue

                    match = _MOBLY_CLASS_HEADER_REGEX.match(line)
                    if match:
                        current_class = match.group("class_name")
                        continue

                    # Capture tests under the current class header
                    if current_class:
                        clean_lines.append(line)

                if clean_lines:
                    output.stdout = "\n".join(clean_lines)

            return output

    async def enumerate_test_cases(
        self,
        recorder: event.EventRecorder,
        parent: event.Id | None = None,
    ) -> command.CommandOutput | None:
        """Enumerate test cases for this test.

        This method dispatches to specific enumeration logic based on test type.

        Args:
            recorder (event.EventRecorder): Recorder for events.
            parent (event.Id | None): Parent event ID.

        Returns:
            command.CommandOutput | None: Command output if successful.
        """
        if self._test.build.test.list_cases_argument == "list_mobly_tests":
            return await self.enumerate_mobly_test(recorder, parent)

        cmd = self.enumerate_cases_command_line()
        if not cmd:
            return None

        # Standard enumeration (e.g. device tests)
        return await run_command(
            *cmd,
            recorder=recorder,
            parent=parent,
            print_verbatim=False,
            env=self.environment(),
        )

    def environment(self) -> dict[str, str] | None:
        """Format environment variables needed to run the test.

        Returns:
            dict[str, str] | None: Environment for
                the test, or None if no environment is needed.
        """
        env = self._flags.computed_env()
        if (
            self._test.build.test.path
            or self._test.is_e2e_test()
            or self._use_test_pilot()
        ):
            env.update(
                {
                    "CWD": self._exec_env.out_dir,
                }
            )
        if self._use_test_pilot():
            if self._device_env is not None:
                # TODO(https://fxbug.dev/550548948): don't assume x64 host
                env.update(
                    {
                        "FUCHSIA_DEVICE_ADDR": self._device_env.address,
                        "FUCHSIA_SSH_KEY": self._device_env.private_key_path,
                        "FUCHSIA_HOST_TOOLS": "./host_x64",
                    }
                )
            if self._flags.extra_args:
                custom_args = " ".join(self._flags.extra_args)
                env.update(
                    {
                        "FUCHSIA_CUSTOM_TEST_ARGS": custom_args,
                    }
                )

        if self._test.is_e2e_test() and self._device_env is not None:
            env.update(
                {
                    "FUCHSIA_DEVICE_ADDR": self._device_env.address,
                    "FUCHSIA_SSH_PORT": self._device_env.port,
                    "FUCHSIA_SSH_KEY": self._device_env.private_key_path,
                    "FUCHSIA_NODENAME": self._device_env.name,
                }
            )

        if self._exec_env.usb_socket_path:
            env.update(
                {
                    "FUCHSIA_TEST_FFX_USB_SOCKET_PATH": self._exec_env.usb_socket_path,
                }
            )

        return None if not env else env

    def should_symbolize(self) -> bool:
        """Determine if we should symbolize the output of this test.

        Returns:
            bool: True if we should run the output through a symbolizer, False otherwise.
        """
        return self._test.info.execution is not None

    async def run(
        self,
        recorder: event.EventRecorder,
        flags: args.Flags,
        parent: event.Id,
        timeout: float | None = None,
        abort_signal: asyncio.Event | None = None,
    ) -> command.CommandOutput:
        """Asynchronously execute this test.

        Args:
            recorder (event.EventRecorder): Recorder for events.
            flags (args.Flags): Command flags to control output.
            parent (event.Id): Parent event to nest the execution under.
            timeout (float, optional): If set, timeout after this number of seconds.
            abort_event (asyncio.Event, optional): If set and signaled, abort this test.

        Raises:
            TestFailed: If the test reported failure.
            TestTimeout: If the test timed out.
            TestSkipped: If the test should not run.

        Returns:
            command.CommandOutput: The output of executing this command.
        """
        if self._test.is_boot_test():
            raise TestSkipped(
                "Boot tests are not supported by `fx test`. Use `fx run-boot-test` or `fx core-tests`."
            )
        if self._test.is_e2e_test() and not flags.e2e:
            raise TestSkipped(
                "Skipping optional end to end test. Pass --e2e to execute this test."
            )
        exec_env = self._exec_env

        symbolizer_args = None
        if self.should_symbolize():
            symbolizer_args = exec_env.fx_cmd_line("ffx", "debug", "symbolize")

        resolved_test_cases = None
        if (
            self._test.build.test.list_cases_argument == "list_mobly_tests"
            and flags.test_filter
        ):
            enumeration_output = await self.enumerate_test_cases(
                recorder, parent
            )
            if enumeration_output and enumeration_output.return_code == 0:
                all_cases = enumeration_output.stdout.splitlines()
                resolved_test_cases = []
                for case in all_cases:
                    for filter_str in flags.test_filter:
                        if filter_str in case:
                            resolved_test_cases.append(case)
                            break
                if not resolved_test_cases:
                    raise TestSkipped(
                        f"No test cases matched filters: {flags.test_filter}"
                    )
            else:
                raise TestCouldNotRun(
                    f"Failed to enumerate test cases for filtering. Output: {enumeration_output.stderr if enumeration_output else 'None'}"
                )

        command = self.command_line(test_cases=resolved_test_cases)
        env = self.environment() or {}

        outdir = self._outdir
        maybe_temp_dir: tempfile.TemporaryDirectory[str] | None = None
        if not outdir:
            maybe_temp_dir = tempfile.TemporaryDirectory()
            outdir = maybe_temp_dir.name
        if not os.path.exists(outdir):
            os.makedirs(outdir)

        # Update the outdir to match the current working directory for the test command (if any).
        # Only do this if the output directory is a relative path, otherwise keep it as is.
        if "CWD" in env and not os.path.isabs(outdir):
            outdir = os.path.relpath(outdir, env["CWD"])

        env.update(
            {
                "FUCHSIA_TEST_OUTDIR": outdir,
            }
        )

        # We add a grace period when timing out in order to give the test itself time to time
        # out first. If it fails to terminate before the grace period expires, we terminate the
        # process.
        timeout = self._calculate_timeout()
        if timeout is not None:
            timeout += self._flags.timeout_grace_period

        try:
            output = await run_command(
                *command,
                recorder=recorder,
                parent=parent,
                print_verbatim=flags.output,
                symbolizer_args=symbolizer_args,
                env=env,
                timeout=timeout,
                abort_signal=abort_signal,
            )
        finally:
            if maybe_temp_dir is not None:
                files: list[str] = []
                for prefix, _, names in os.walk(maybe_temp_dir.name):
                    files.extend(
                        [
                            os.path.relpath(
                                os.path.join(prefix, n), maybe_temp_dir.name
                            )
                            for n in names
                        ]
                    )
                if files:
                    name_list = statusinfo.ellipsize(", ".join(files), 100)
                    recorder.emit_instruction_message(
                        f"Deleting {len(files)} files at {maybe_temp_dir.name}: {name_list}"
                    )
                    recorder.emit_instruction_message(
                        "To keep these files, set --ffx-output-directory."
                    )
                maybe_temp_dir.cleanup()

        if not output:
            raise TestFailed("Failed to run the test command")
        elif output.return_code != 0 or output.was_timeout:
            if not flags.output:
                # If output wasn't streamed live, print the header for the failure.
                recorder.emit_info_message(
                    f"\n{statusinfo.error_highlight(self._test.name(), style=flags.style)}:\n"
                )

            if flags.gemini_analysis is not None:
                error_log_parts = []
                if output.stdout:
                    error_log_parts.append(output.stdout)
                if output.stderr:
                    error_log_parts.append(output.stderr)
                if not output.stdout and not output.stderr:
                    error_log_parts.append("<No command output>")

                error_log = "\n".join(error_log_parts)
                if error_log and not error_log.endswith("\n"):
                    error_log += "\n"

                if error_log:
                    api_key = self._exec_env.gemini_api_key

                    if not api_key:
                        recorder.emit_warning_message(
                            "Gemini analysis skipped: GEMINI_API_KEY environment variable not set."
                        )
                    else:
                        # TODO(https://fxbug.dev/456511584): change gemini_analysis call to use a built binary
                        gemini_tool_path = os.path.join(
                            self._exec_env.fuchsia_dir,
                            "tools/gemini_analysis/gemini_analysis.py",
                        )
                        gemini_output = await run_command(
                            gemini_tool_path,
                            "--gemini-model",
                            flags.gemini_model,
                            "--verbosity",
                            str(flags.gemini_analysis),
                            recorder=recorder,
                            parent=parent,
                            print_verbatim=True,
                            input_bytes=error_log.encode(),
                            env={"GEMINI_API_KEY": api_key},
                        )
                        if not gemini_output or gemini_output.return_code != 0:
                            recorder.emit_warning_message(
                                "Gemini analysis failed."
                            )
                            if gemini_output and gemini_output.stderr:
                                recorder.emit_verbatim_message(
                                    gemini_output.stderr
                                )
            elif not flags.output:
                # gemini is off, give output
                if output.stdout:
                    recorder.emit_verbatim_message(output.stdout)
                if output.stderr:
                    recorder.emit_verbatim_message(output.stderr)
                if not output.stderr and not output.stdout:
                    recorder.emit_verbatim_message("<No command output>")

            if output.was_timeout:
                raise TestTimeout(
                    f"Test exceeded runtime of {timeout} seconds",
                    command_output=output,
                )
            else:
                raise TestFailed("Test reported failure", command_output=output)
        return output

    def _get_component_url(self) -> str | None:
        """Get the final component URL to execute for this test.

        If this test is not a component test, return None.

        Raises:
            TestCouldNotRun: If we cannot determine the merkle hash for this test.

        Returns:
            str | None: The final URL to execute (optionally with
                hash), or None if this is not a component test.
        """
        if self._test.info.execution is None:
            return None

        execution = self._test.info.execution

        component_url = execution.component_url
        if self._flags.use_package_hash:
            try:
                package_repo = (
                    package_repository.PackageRepository.from_env_cached(
                        self._exec_env
                    )
                )
                component_url = package_repo.resolve_component_url(
                    component_url
                )
            except package_repository.PackageRepositoryError as e:
                raise TestCouldNotRun(
                    f"Could not load a Merkle hash for this test ({str(e)}).\nTry running fx build."
                    f"{package_repository.MERKLE_ERROR_HELP_SUFFIX}"
                    if package_repository.MERKLE_ERROR_HELP_SUFFIX not in str(e)
                    else str(e)
                )
        return component_url

    def _use_test_pilot(self) -> bool:
        """Should this test use test_pilot.


        Returns:
            True if experimental flag is enabled and the test supports new
            interface.
        """
        return (
            self._flags.use_test_pilot
            and self._test.build.test.new_path is not None
        )

    def _calculate_timeout(self) -> float | None:
        # Use the config/default timeout if not specified on the command line. If a zero timeout
        # is specified, do not time out.
        if self._flags.timeout is None:
            if self._test.build.test.timeout_secs is not None:
                return self._test.build.test.timeout_secs
            else:
                return DEFAULT_TIMEOUT
        elif self._flags.timeout > 0:
            return self._flags.timeout
        else:
            return None


class DeviceConfigError(Exception):
    """There was an error reading the device configuration"""


def _parse_device_address(
    target_line: str,
    raw_output: str = "",
    stderr: str = "",
    return_code: int = 0,
) -> tuple[str, str]:
    """Parse and validate a device target address and port.

    Args:
        target_line: The raw address string (e.g. from `ffx target list`).
        raw_output: Raw stdout from command, for error reporting.
        stderr: Raw stderr from command, for error reporting.
        return_code: Process return code, for error reporting.

    Returns:
        A tuple of (address, port).

    Raises:
        DeviceConfigError: If the address or port is invalid or cannot be parsed.
    """
    target_line = target_line.strip()
    if ":" not in target_line:
        raise DeviceConfigError(
            f"Could not parse target address: {raw_output or target_line!r}.\n"
            f"Expected 'ip:port' format.\n"
            f"Return code: {return_code},\n"
            f"Stderr: {stderr!r}"
        )

    if target_line.startswith("["):
        closing_bracket = target_line.find("]")
        if closing_bracket == -1:
            raise DeviceConfigError(
                f"Could not parse target address: {raw_output or target_line!r}.\n"
                f"Missing closing bracket in IPv6 address.\n"
                f"Return code: {return_code},\n"
                f"Stderr: {stderr!r}"
            )
        ip_inside = target_line[1:closing_bracket].strip()
        if not ip_inside:
            raise DeviceConfigError(
                f"Could not parse target address: {raw_output or target_line!r}.\n"
                f"Empty IPv6 address in brackets."
            )

        base_ip = ip_inside
        if "%" in ip_inside:
            base_ip, scope_id = ip_inside.split("%", 1)
            if not scope_id:
                raise DeviceConfigError(
                    f"Could not parse target address: {raw_output or target_line!r}.\n"
                    f"Empty scope ID in IPv6 address."
                )

        try:
            ipaddress.IPv6Address(base_ip)
        except ValueError as e:
            raise DeviceConfigError(
                f"Invalid IPv6 address in target: {ip_inside!r}: {e}"
            )

        ip = target_line[0 : closing_bracket + 1]
        remainder = target_line[closing_bracket + 1 :].strip()
        if remainder:
            if not remainder.startswith(":") or len(remainder) == 1:
                raise DeviceConfigError(
                    f"Could not parse target address: {raw_output or target_line!r}.\n"
                    f"Invalid or missing port after closing bracket."
                )
            port = remainder[1:].strip()
        else:
            port = "22"
    elif target_line.startswith(("usb:cid:", "vsock:cid:")):
        last_colon_index = target_line.rfind(":")
        ip = target_line[0:last_colon_index].strip()
        port = target_line[last_colon_index + 1 :].strip()
        if not port.isdigit():
            raise DeviceConfigError(
                f"Invalid CID in target address: {port!r}.\n"
                f"Expected non-negative integer."
            )
        return ip, port
    elif target_line.count(":") > 1:
        # Unbracketed IPv6 address without port (e.g. fe80::1 or fe80::1%eth0)
        base_ip = target_line
        if "%" in target_line:
            base_ip, scope_id = target_line.split("%", 1)
            if not scope_id:
                raise DeviceConfigError(
                    f"Could not parse target address: {raw_output or target_line!r}.\n"
                    f"Empty scope ID in IPv6 address."
                )
        try:
            ipaddress.IPv6Address(base_ip)
        except ValueError as e:
            raise DeviceConfigError(
                f"Invalid IPv6 address in target: {target_line!r}: {e}"
            )
        ip = target_line
        port = "22"
    else:
        # IPv4 or hostname with port (e.g. 192.168.1.1:8022 or localhost:22)
        last_colon_index = target_line.rfind(":")
        ip = target_line[0:last_colon_index].strip()
        port = target_line[last_colon_index + 1 :].strip()
        if not ip:
            raise DeviceConfigError(
                f"Could not parse target address: {raw_output or target_line!r}.\n"
                f"Missing host/IP before colon."
            )
        if not port:
            raise DeviceConfigError(
                f"Could not parse target address: {raw_output or target_line!r}.\n"
                f"Missing port after colon."
            )

    if not port.isdigit() or not (1 <= int(port) <= 65535):
        raise DeviceConfigError(
            f"Invalid port in target address: {port!r}.\n"
            f"Expected integer between 1 and 65535."
        )

    return ip, port


async def get_device_environment_from_exec_env(
    exec_env: environment.ExecutionEnvironment,
    recorder: event.EventRecorder | None = None,
) -> environment.DeviceEnvironment:
    # Wait for the target to become ready and reachable.
    # This is more efficient than polling ffx target list in a sleep loop.
    wait_output = await run_command(
        *exec_env.fx_cmd_line("ffx", "target", "wait", "-t", "10"),
        recorder=recorder,
        timeout=_DEVICE_PROBE_TIMEOUT_SECONDS,
    )
    if not wait_output or wait_output.return_code != 0:
        raise DeviceConfigError("Failed to wait for target to become reachable")

    target_output = await run_command(
        *exec_env.fx_cmd_line("ffx", "target", "default", "get"),
        recorder=recorder,
        timeout=_DEVICE_PROBE_TIMEOUT_SECONDS,
    )
    if not target_output or target_output.return_code != 0:
        raise DeviceConfigError(
            "Failed to get the target name. Please ensure you have set a default target using 'fx set-device'. See 'fx set-device --help' for more details on target resolution."
        )
    target_name = target_output.stdout.strip()

    ssh_output = await run_command(
        *exec_env.fx_cmd_line(
            "ffx",
            "target",
            "list",
            "--format",
            "addresses-with-scope",
            target_name,
        ),
        recorder=recorder,
        timeout=_DEVICE_PROBE_TIMEOUT_SECONDS,
    )

    if (
        not ssh_output
        or ssh_output.return_code != 0
        or not ssh_output.stdout.strip()
    ):
        raise DeviceConfigError("Failed to get the ssh address of the target")

    target_line = ssh_output.stdout.strip().splitlines()[-1].strip()
    ip, port = _parse_device_address(
        target_line,
        raw_output=ssh_output.stdout,
        stderr=ssh_output.stderr,
        return_code=ssh_output.return_code,
    )

    # get the configured private key. Ideally, the private key usage
    # should be an implementation detail internal to ffx commands.
    ssh_key_output = await run_command(
        *exec_env.fx_cmd_line(
            "ffx",
            "config",
            "get",
            "--process",
            "file",
            "ssh.priv",
        ),
        recorder=recorder,
        timeout=_DEVICE_PROBE_TIMEOUT_SECONDS,
    )
    if not ssh_key_output or ssh_key_output.return_code != 0:
        msg = "No return information"
        if ssh_key_output:
            msg = ssh_key_output.stderr
        raise DeviceConfigError(
            f"Failed to get private ssh key: {msg}. Please check your ffx configuration by running 'ffx config get ssh.priv' or 'ffx config env'."
        )
    ssh_path = ssh_key_output.stdout.strip()
    # remove any double quotes around the path
    ssh_path = ssh_path.replace('"', "")

    if not os.path.exists(ssh_path):
        raise DeviceConfigError(
            f"Path returned by 'ssh.priv' does not exist: {ssh_path}. Please check your ffx configuration by running 'ffx config get ssh.priv'. You can also check where config files are located by running 'ffx config env'."
        )

    return environment.DeviceEnvironment(
        address=ip, port=port, name=target_name, private_key_path=ssh_path
    )


async def run_command(
    name: str,
    *args: str,
    recorder: event.EventRecorder | None = None,
    parent: event.Id | None = None,
    print_verbatim: bool = False,
    symbolizer_args: list[str] | None = None,
    env: dict[str, str] | None = None,
    timeout: float | None = None,
    abort_signal: asyncio.Event | None = None,
    quiet_mode: bool = False,
    input_bytes: bytes | None = None,
    do_not_log_output: bool = False,
) -> command.CommandOutput | None:
    """Utility method to run a test command asynchronously.

    Args:
        name (str): Command to run.
        args (list[str]): Arguments to the command.
        recorder (event.EventRecorder | None):
            Recorder for events. Defaults to None.
        parent (event.Id | None): Parent event ID for reporting.
            Defaults to None.
        print_verbatim (bool, optional): If set, record verbatim
            output events for stdout and stderr. Defaults to False.
        symbolize (bool, optional): If true, pipe output through
            symbolizer. Defaults to False.
        env (dict[str, str], optional):
            Environment to pass to the command. Defaults to None.
        timeout (float, optional): The number of seconds to wait before timing out.
        abort_signal (asyncio.Event, optional): If set, when the
            event is signaled this command will attempt a graceful
            termination.
        quiet_mode (bool, optional): If set, this command will run
            quietly in the background and will not announce cancellation or
            clutter the running task list.
        do_not_log_output (bool, optional): If set, this command will not log its output.
            This is useful for noisy programs whose output may be too much for
            downstream processing.

    Returns:
        command.CommandOutput | None: The command output if it could
            be executed, None otherwise.
    """
    event_id: event.Id | None = None
    abort_task: asyncio.Task[None] | None = None
    if recorder is not None:
        logged_env = env
        if env:
            logged_env = {
                k: ("<REDACTED>" if "API_KEY" in k.upper() else v)
                for k, v in env.items()
            }
        event_id = recorder.emit_program_start(
            name, list(args), logged_env, parent=parent, quiet_mode=quiet_mode
        )
    try:
        started = await command.AsyncCommand.create(
            name,
            *args,
            symbolizer_args=symbolizer_args,
            env=env,
            timeout=timeout,
            input_bytes=input_bytes,
        )

        async def handle_abort() -> None:
            if abort_signal is not None:
                await abort_signal.wait()
                if recorder is not None and not quiet_mode:
                    recorder.emit_info_message(f"Aborting {name}...")
                started.terminate()
                runner_task = getattr(started, "_runner_task", None)
                if runner_task is not None:
                    try:
                        await asyncio.wait_for(
                            asyncio.shield(runner_task),
                            timeout=5.0,
                        )
                        return
                    except asyncio.TimeoutError:
                        pass
                else:
                    await asyncio.sleep(5)
                if recorder is not None:
                    recorder.emit_warning_message(
                        f"{name} did not terminate in time, killing it"
                    )
                started.kill()

        abort_task = asyncio.Task(handle_abort())

        def handle_event(current_event: command.CommandEvent) -> None:
            if recorder is not None:
                assert event_id is not None
                if (
                    isinstance(current_event, command.StdoutEvent)
                    and not do_not_log_output
                ):
                    recorder.emit_program_output(
                        event_id,
                        current_event.text.decode(errors="replace"),
                        stream=event.ProgramOutputStream.STDOUT,
                        print_verbatim=print_verbatim,
                    )
                if (
                    isinstance(current_event, command.StderrEvent)
                    and not do_not_log_output
                ):
                    recorder.emit_program_output(
                        event_id,
                        current_event.text.decode(errors="replace"),
                        stream=event.ProgramOutputStream.STDERR,
                        print_verbatim=print_verbatim,
                    )
                if isinstance(current_event, command.TerminationEvent):
                    recorder.emit_program_termination(
                        event_id, current_event.return_code
                    )

        ret = await started.run_to_completion(callback=handle_event)
        return ret
    except command.AsyncCommandError as e:
        if recorder is not None:
            assert event_id is not None
            recorder.emit_program_termination(event_id, -1, error=str(e))
        return None
    finally:
        if abort_task is not None:
            abort_task.cancel()
