from __future__ import annotations

import contextlib
import io
import json
from pathlib import Path
import sys
import unittest

from unuforge import cli


ROOT = Path(__file__).resolve().parents[1]
TESTS_DIR = Path(__file__).resolve().parent
if str(TESTS_DIR) not in sys.path:
    sys.path.insert(0, str(TESTS_DIR))


class CliTests(unittest.TestCase):
    def _invoke(self, *argv: str) -> tuple[int, str, str]:
        stdout = io.StringIO()
        stderr = io.StringIO()
        code = 0
        with contextlib.redirect_stdout(stdout), contextlib.redirect_stderr(stderr):
            result = cli.main(list(argv))
            if isinstance(result, int):
                code = result
        return code, stdout.getvalue(), stderr.getvalue()

    def test_preset_inspect_json(self) -> None:
        code, stdout, stderr = self._invoke(
            "preset",
            "inspect",
            "--preset",
            str(ROOT / "fixtures" / "presets" / "v2-sample.json"),
            "--json",
        )
        self.assertEqual(code, 0, stderr)
        payload = json.loads(stdout)
        self.assertEqual(payload["schema_version"], 2)
        self.assertEqual(payload["project"]["name"], "sample")

    def test_profiles_list_json(self) -> None:
        code, stdout, stderr = self._invoke(
            "profiles",
            "list",
            "--preset",
            str(ROOT / "fixtures" / "presets" / "v2-sample.json"),
            "--json",
        )
        self.assertEqual(code, 0, stderr)
        payload = json.loads(stdout)
        self.assertEqual(payload["profiles"], ["code-quality.workflow", "sample.profile"])

    def test_profiles_run_dry_run_json_uses_host_adapter(self) -> None:
        code, stdout, stderr = self._invoke(
            "profiles",
            "run",
            "sample.profile",
            "--preset",
            str(ROOT / "fixtures" / "presets" / "v2-sample.json"),
            "--host-adapter",
            "stub_host",
            "--dry-run",
            "--json",
            "--",
            "--flag",
        )
        self.assertEqual(code, 0, stderr)
        payload = json.loads(stdout)
        self.assertEqual(payload["runner"], "command")
        self.assertEqual(payload["command"], ["echo", "sample.profile", "--flag"])

    def test_actions_run_dry_run_json_uses_host_adapter(self) -> None:
        code, stdout, stderr = self._invoke(
            "actions",
            "run",
            "promote",
            "--preset",
            str(ROOT / "fixtures" / "presets" / "v2-sample.json"),
            "--host-adapter",
            "stub_host",
            "--dry-run",
            "--json",
            "--",
            "--with-web",
        )
        self.assertEqual(code, 0, stderr)
        payload = json.loads(stdout)
        self.assertEqual(payload["runner"], "command")
        self.assertEqual(payload["command"], ["echo", "promote", "--with-web"])


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