from __future__ import annotations

import subprocess
from typing import Annotated

from sunwaee.config import get_default_workspace
from sunwaee.core.audit import append_log
from sunwaee.core.tools import err, ok, tool

_TIMEOUT = 60


def _git_snapshot(cwd: str) -> dict:
    """Capture git diff and status after a command runs."""

    def _run(args: list[str]) -> str:
        try:
            return subprocess.run(
                args, capture_output=True, text=True, cwd=cwd, timeout=10
            ).stdout.strip()
        except Exception:  # pragma: no cover
            return ""

    diff = _run(["git", "diff"])
    status = _run(["git", "status", "--short"])
    return {"diff": diff, "status": status}


@tool(
    "Run a shell command in cwd. "
    "Always provide a short human-readable comment describing what the command does — "
    "it is shown to the user instead of the raw command. "
    "Returns stdout, stderr, exit_code, and git snapshot (diff + status) if in a git repo. "
    "The git snapshot is persisted in the session for future reference."
)
def shell(
    command: Annotated[str, "Shell command to execute (run via bash -c)"],
    comment: Annotated[
        str, "Short human-readable description shown to the user in the REPL"
    ],
) -> str:
    ws = get_default_workspace()
    try:
        result = subprocess.run(
            ["bash", "-c", command],
            capture_output=True,
            text=True,
            timeout=_TIMEOUT,
        )
    except subprocess.TimeoutExpired:  # pragma: no cover
        append_log(ws, "shell", "run", ok=False, item_title=comment)
        return err(f"Command timed out after {_TIMEOUT}s: {command!r}")
    except Exception as e:  # pragma: no cover
        append_log(ws, "shell", "run", ok=False, item_title=comment)
        return err(str(e))

    git = _git_snapshot(".")
    append_log(
        ws,
        "shell",
        "run",
        ok=result.returncode == 0,
        item_title=comment,
        args={"exit_code": result.returncode},
    )
    return ok(
        {
            "comment": comment,
            "command": command,
            "exit_code": result.returncode,
            "stdout": result.stdout,
            "stderr": result.stderr,
            "git_diff": git["diff"],
            "git_status": git["status"],
        }
    )


TOOLS = [shell._tool]
