#!/usr/bin/env python3
"""Pure-function tests for seat_implementer_exec."""

from __future__ import annotations

import os
import sys
import tempfile
import unittest
import unittest.mock


_LIB = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "lib")
if _LIB not in sys.path:
    sys.path.insert(0, _LIB)

from seat_implementer_exec import (  # noqa: E402
    FORBIDDEN_ENV,
    build_arg_parser,
    build_implementer_env,
    require_root_transition,
    validate_args,
    validate_command,
)
from seat_scope_entry import TMUX_CONF, write_tmux_conf  # noqa: E402


class SeatImplementerExecTests(unittest.TestCase):
    def test_build_implementer_env_strips_forbidden(self) -> None:
        parser = build_arg_parser()
        ns = parser.parse_args([
            "--seat-id", "seat-x",
            "--seat-host", "debian1",
            "--seat-model", "gpt-5.6-terra",
            "--socket", "/tmp/s.sock",
            "--launcher", "/home/op/.claude/bin/seat-launcher",
            "--claude-bin", "/home/op/.local/bin/claude",
            "--guard-bin", "/home/op/.local/share/overdeck/seat-guard/current/bin",
            "--checkout", "/home/op/seats/seat-x/repo",
            "--state-dir", "/home/op/.local/state/overdeck/seats/seat-x",
            "--implementer-home", "/var/lib/overdeck/seat-runtime/seat-x/home",
            "--",
            "tmux",
        ])
        env = build_implementer_env(ns, 999, "ods-seat-x")
        for key in FORBIDDEN_ENV:
            self.assertNotIn(key, env)
        self.assertEqual(env["OVERDECK_CLAUDE_BIN"], ns.claude_bin)
        self.assertNotIn("GIT_CONFIG_GLOBAL", env)

    def test_validate_command_requires_tmux_conf(self) -> None:
        with self.assertRaises(SystemExit):
            validate_command(
                ["tmux", "-S", "/tmp/s.sock", "new-session", "--", "/bin/launcher"],
                "/bin/launcher",
                "/tmp/s.sock",
                "/tmp/tmux-seat.conf",
            )

    def test_write_tmux_conf_uses_control_path(self) -> None:
        with tempfile.TemporaryDirectory() as tmp:
            os.environ["OVERDECK_SEAT_CONTROL_BASE"] = os.path.join(tmp, "control")
            os.environ["OVERDECK_SEAT_TEST_MODE"] = "1"
            path = write_tmux_conf("seat-x", 1000, 1000)
            self.assertIn("/control/seat-x/tmux-seat.conf", path)
            with open(path, encoding="utf-8") as fh:
                text = fh.read()
            self.assertNotIn("systemd", text)
            self.assertEqual(text, TMUX_CONF)

    def test_validate_args_requires_separator(self) -> None:
        parser = build_arg_parser()
        ns = parser.parse_args([
            "--seat-id", "seat-x",
            "--seat-host", "debian1",
            "--seat-model", "gpt-5.6-terra",
            "--socket", "/tmp/s.sock",
            "--launcher", "/home/op/.claude/bin/seat-launcher",
            "--claude-bin", "/home/op/.local/bin/claude",
            "--guard-bin", "/home/op/.local/share/overdeck/seat-guard/current/bin",
            "--checkout", "/home/op/seats/seat-x/repo",
            "--state-dir", "/home/op/.local/state/overdeck/seats/seat-x",
            "--implementer-home", "/var/lib/overdeck/seat-runtime/seat-x/home",
            "tmux",
        ])
        with self.assertRaises(SystemExit):
            validate_args(ns)

    def test_require_root_transition_accepts_sudo_env(self) -> None:
        with unittest.mock.patch("seat_implementer_exec.os.geteuid", return_value=0):
            with unittest.mock.patch.dict(os.environ, {"SUDO_UID": "1000", "SUDO_USER": "fixture-user"}, clear=False):
                require_root_transition(1000)

    def test_require_root_transition_rejects_missing_sudo_env(self) -> None:
        with unittest.mock.patch("seat_implementer_exec.os.geteuid", return_value=0):
            with unittest.mock.patch.dict(os.environ, {}, clear=True):
                with self.assertRaises(SystemExit):
                    require_root_transition(1000)


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