"""Thread management functions for the Amp SDK."""

from __future__ import annotations

import asyncio
from typing import Optional

from .core import _find_amp_cli, _kill_process, _raise_if_process_failed
from .exceptions import AmpError, CLINotFoundError
from .types import ThreadsMarkdownOptions, ThreadsNewOptions


async def _run_thread_command(args: list[str]) -> str:
    """Run a simple CLI command and return stdout."""
    cli_cmd = _find_amp_cli()
    full_cmd = cli_cmd + args

    try:
        proc = await asyncio.create_subprocess_exec(
            *full_cmd,
            stdin=asyncio.subprocess.PIPE,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE,
        )
    except FileNotFoundError as e:
        raise CLINotFoundError(f"Failed to start CLI: {e}") from e
    except Exception as e:
        raise AmpError(f"Failed to start process: {e}") from e

    try:
        stdout_bytes, stderr_bytes = await proc.communicate()
        stdout = stdout_bytes.decode("utf-8", errors="replace").strip()
        stderr = stderr_bytes.decode("utf-8", errors="replace")

        _raise_if_process_failed(proc.returncode, stderr)
        return stdout
    except Exception:
        await _kill_process(proc)
        raise


async def _new_thread(options: Optional[ThreadsNewOptions] = None) -> str:
    """
    Create a new empty thread and return its ID.

    Args:
        options: Optional configuration options for the new thread

    Returns:
        The thread ID

    Raises:
        CLINotFoundError: If the Amp CLI cannot be found
        ProcessError: If the CLI process fails
        AmpError: For other errors
    """
    if options is None:
        options = ThreadsNewOptions()

    args = ["threads", "new"]
    if options.visibility:
        args.extend(["--visibility", options.visibility])

    return await _run_thread_command(args)


async def _get_thread_markdown(options: ThreadsMarkdownOptions) -> str:
    """
    Get a thread rendered as markdown.

    Args:
        options: Options containing the thread ID

    Returns:
        The thread content as markdown

    Raises:
        CLINotFoundError: If the Amp CLI cannot be found
        ProcessError: If the CLI process fails
        AmpError: For other errors
    """
    return await _run_thread_command(["threads", "markdown", options.thread_id])


# Namespace
new = _new_thread
markdown = _get_thread_markdown
