# 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 argparse
import asyncio
import json
import os
import subprocess
import sys
from pathlib import Path
from typing import Final

from fx_cmd.lib import FxCmd
from shared.protocol import (
    PROTOCOL_VERSION,
    BaseRequest,
    HelloRequest,
    StartRequest,
    deserialize_request,
    make_request,
    serialize,
)

# The maximum number of seconds that we will wait for the daemon to start. In particular, this is
# how long we will wait for the daemon to write into the pipe FD that we pass to it when we start
# the new process.
DAEMON_STARTUP_TIMEOUT_SECS: Final[float] = 10.0
# TODO(https://fxbug.dev/504962182): Replace this with something more appropriate.
UDS_PATH: Final[Path] = Path("/tmp/fx-debug-daemon.sock")


async def main(args: list[str]) -> int:
    # Define argument parser for the CLI.
    # It supports a raw JSON input or specific subcommands.
    parser = argparse.ArgumentParser(description="fx debug cli")
    parser.add_argument("--json", help="JSON request string")
    subparsers = parser.add_subparsers(dest="command", required=False)

    start_parser = subparsers.add_parser("start", help="Start the daemon")
    start_parser.add_argument(
        "--port", type=int, help="Port for DAP server", default=None
    )
    subparsers.add_parser("stop", help="Stop the daemon")
    subparsers.add_parser("get-state", help="Get state of session")
    attach_parser = subparsers.add_parser("attach", help="Attach to a process")
    attach_parser.add_argument("filter", help="Process name or ID to attach to")
    subparsers.add_parser("threads", help="Get list of threads")

    continue_parser = subparsers.add_parser("continue", help="Resume execution")
    continue_parser.add_argument(
        "thread_id", type=int, help="Thread ID to resume"
    )
    continue_parser.add_argument(
        "--single-thread",
        action="store_true",
        default=None,
        help="Resume only the specified thread",
    )

    pause_parser = subparsers.add_parser("pause", help="Interrupt execution")
    pause_parser.add_argument("thread_id", type=int, help="Thread ID to pause")

    stack_trace_parser = subparsers.add_parser(
        "stackTrace",
        help="Get stack trace of a thread. This will automatically pause the given thread when called.",
    )
    stack_trace_parser.add_argument(
        "thread_id", type=int, help="Thread ID to get stack trace for"
    )

    parsed_args = parser.parse_args(args)

    if parsed_args.json and parsed_args.command:
        print("Error: --json and command are mutually exclusive")
        return 1

    if not parsed_args.json and not parsed_args.command:
        print("Error: Either --json or a command must be provided")
        return 1

    # Process the parsed arguments and dispatch to commands.
    req: BaseRequest | None = None
    if parsed_args.json:
        try:
            req = deserialize_request(parsed_args.json)
            if isinstance(req, StartRequest):
                return await start_daemon(req.port)
        except json.JSONDecodeError as e:
            print(f"Error: Invalid JSON: {e}")
            return 1
        except ValueError as e:
            print(f"Error: {e}")
            return 1
    elif parsed_args.command == "start":
        return await start_daemon(parsed_args.port)
    elif parsed_args.command:
        try:
            args_dict = vars(parsed_args)
            req = make_request(args_dict)
            return await send_command(req)
        except ValueError as e:
            print(f"Error: {e}")
            return 1

    assert req is not None
    assert isinstance(req, BaseRequest)
    return await send_command(req)


async def _try_connect_and_handshake() -> bool | None:
    """Attempts to connect to the UDS and perform handshake.

    Returns:
        True if handshake succeeded.
        False if handshake failed (version mismatch or error response).
        None if connection failed (socket not ready yet).
    """
    try:
        reader, writer = await asyncio.open_unix_connection(UDS_PATH)
    except (ConnectionRefusedError, FileNotFoundError):
        return None
    except Exception as e:
        print(
            json.dumps(
                {
                    "success": False,
                    "message": f"Error connecting to daemon: {e}",
                }
            )
        )
        return False

    try:
        req = HelloRequest(version=PROTOCOL_VERSION)
        writer.write(serialize(req).encode("utf-8"))
        await writer.drain()

        response_line = await reader.readline()
        writer.close()
        await writer.wait_closed()

        if not response_line:
            print(
                json.dumps(
                    {
                        "success": False,
                        "message": "No response received during handshake",
                    }
                )
            )
            return False

        resp_dict = json.loads(response_line.decode("utf-8"))
        if not resp_dict.get("success"):
            print(
                json.dumps(
                    {
                        "success": False,
                        "message": f"Handshake failed: {resp_dict.get('message')}",
                    }
                )
            )
            return False

        body = resp_dict.get("body", {})
        daemon_version = body.get("protocol_version")
        if daemon_version != PROTOCOL_VERSION:
            print(
                json.dumps(
                    {
                        "success": False,
                        "message": f"Protocol version mismatch. CLI: {PROTOCOL_VERSION}, Daemon: {daemon_version}",
                    }
                )
            )
            return False

        return True
    except Exception as e:
        print(
            json.dumps(
                {
                    "success": False,
                    "message": f"Error during handshake: {e}",
                }
            )
        )
        return False


async def start_daemon(port: int | None) -> int:
    """Spawns the daemon process and waits for it to be ready."""
    # Check if a daemon is already running. If the socket file exists, attempt
    # to connect to it to verify if it is active. If the connection is refused,
    # the socket is stale (e.g., from a crash or rapid restart) and can be safely removed.
    if UDS_PATH.exists():
        try:
            reader, writer = await asyncio.open_unix_connection(UDS_PATH)
            writer.close()
            await writer.wait_closed()
            print(
                json.dumps(
                    {
                        "success": False,
                        "message": f"Daemon socket already exists at {UDS_PATH}",
                    }
                )
            )
            return 1
        except (ConnectionRefusedError, FileNotFoundError):
            UDS_PATH.unlink(missing_ok=True)

    fx_cmd = FxCmd()
    args = ["zxdb-daemon"]
    if port is not None:
        args.extend(["--port", str(port)])

    # Create a pipe for synchronization
    read_fd, write_fd = os.pipe()
    os.set_inheritable(write_fd, True)
    args.append(f"--ready-fd={write_fd}")

    command_line = fx_cmd.command_line(*args)

    try:
        # Spawn daemon process in background
        subprocess.Popen(
            command_line,
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
            start_new_session=True,
            pass_fds=[write_fd],  # Ensure FD is passed to child
        )
        print("Spawning daemon...")

        # Close write end in parent
        os.close(write_fd)

        # Wait for signal on the pipe with timeout
        loop = asyncio.get_running_loop()
        try:
            # Read 1 byte from the pipe
            await asyncio.wait_for(
                loop.run_in_executor(None, os.read, read_fd, 1),
                timeout=DAEMON_STARTUP_TIMEOUT_SECS,
            )
        except asyncio.TimeoutError:
            print(
                json.dumps(
                    {
                        "success": False,
                        "message": "Timed out waiting for daemon to signal readiness.",
                    }
                )
            )
            os.close(read_fd)
            return 1
        except Exception as e:
            print(
                json.dumps(
                    {
                        "success": False,
                        "message": f"Error reading from pipe: {e}",
                    }
                )
            )
            os.close(read_fd)
            return 1
        finally:
            try:
                os.close(read_fd)
            except OSError:
                pass

        # Now that daemon signaled readiness, perform handshake
        result = await _try_connect_and_handshake()
        if result is True:
            print(
                json.dumps(
                    {
                        "success": True,
                        "protocol_version": PROTOCOL_VERSION,
                    }
                )
            )
            return 0
        elif result is None:
            print(
                json.dumps(
                    {
                        "success": False,
                        "message": "Daemon started but failed to respond to handshake in time.",
                    }
                )
            )
            return 1
        else:
            return 1
    except Exception as e:
        print(f"Failed to start daemon: {e}")
        return 1


async def send_command(req: BaseRequest) -> int:
    if not UDS_PATH.exists():
        print(f"Daemon socket not found at {UDS_PATH}. Is it running?")
        return 1

    try:
        reader, writer = await asyncio.open_unix_connection(UDS_PATH)
        writer.write(serialize(req).encode("utf-8"))
        await writer.drain()

        response_line = await reader.readline()
        if response_line:
            print(response_line.decode("utf-8").strip())
        else:
            print("No response received from daemon.")

        if req.command == "stop":
            # Wait for daemon to close connection (EOF)
            try:
                await asyncio.wait_for(reader.read(), timeout=5.0)
            except asyncio.TimeoutError:
                print(
                    "Warning: Timed out waiting for daemon to close connection."
                )

        writer.close()
        await writer.wait_closed()
        return 0
    except Exception as e:
        print(f"Error communicating with daemon: {e}")
        return 1


if __name__ == "__main__":
    sys.exit(asyncio.run(main(sys.argv[1:])))
