from __future__ import annotations

import os
import tempfile
import unittest
from pathlib import Path
from unittest.mock import patch

from core import procs
from core.proc_wrapper import _shell_argv as wrapper_shell_argv
from tools.shell import ShellTool


class ShellSecurityTests(unittest.TestCase):
    def test_shell_argv_uses_explicit_interpreter(self) -> None:
        argv = procs.shell_argv("echo ok")
        wrapper_argv = wrapper_shell_argv("echo ok")
        self.assertEqual(argv, wrapper_argv)
        self.assertEqual(argv[-1], "echo ok")
        if os.name == "nt":
            self.assertEqual(argv[1:4], ["/d", "/s", "/c"])
        else:
            self.assertEqual(argv[:2], ["/bin/sh", "-c"])

    def test_foreground_shell_still_executes_command(self) -> None:
        with tempfile.TemporaryDirectory() as tmp:
            result = ShellTool(base_dir=Path(tmp)).execute("echo shell-ok")
        self.assertIn("shell-ok", result)
        self.assertIn("[exit 0]", result)

    def test_background_shell_persists_explicit_argv(self) -> None:
        with tempfile.TemporaryDirectory() as tmp, patch(
            "tools.shell.procs.count_running", return_value=0
        ), patch("tools.shell.procs.launch_host", return_value=("proc-1", Path(tmp))) as launch:
            result = ShellTool(base_dir=Path(tmp)).execute(
                "echo background-ok", background=True
            )
        self.assertIn("proc_id=proc-1", result)
        kwargs = launch.call_args.kwargs
        self.assertEqual(kwargs["argv"], procs.shell_argv("echo background-ok"))
        self.assertNotIn("shell_cmd", kwargs)


if __name__ == "__main__":
    unittest.main()
