"""Tests for rbsp.runtime.cli -- build_parser, _format_size, main."""

import os
import sys
import unittest

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))

from rbsp.runtime.cli import build_parser, _format_size, main


# ---------------------------------------------------------------------------
# build_parser tests
# ---------------------------------------------------------------------------

class TestBuildParser(unittest.TestCase):
    """Tests for the CLI argument parser construction."""

    def setUp(self):
        self.parser = build_parser()

    def test_parser_prog_name(self):
        self.assertEqual(self.parser.prog, "rbsp")

    def test_init_subcommand(self):
        args = self.parser.parse_args(["init"])
        self.assertEqual(args.command, "init")
        self.assertEqual(args.path, ".")

    def test_init_with_path(self):
        args = self.parser.parse_args(["init", "/some/path"])
        self.assertEqual(args.path, "/some/path")

    def test_index_subcommand(self):
        args = self.parser.parse_args(["index"])
        self.assertEqual(args.command, "index")
        self.assertFalse(args.force)

    def test_index_with_force(self):
        args = self.parser.parse_args(["index", "--force"])
        self.assertTrue(args.force)

    def test_index_with_force_short(self):
        args = self.parser.parse_args(["index", "-f"])
        self.assertTrue(args.force)

    def test_search_subcommand(self):
        args = self.parser.parse_args(["search", "hello", "world"])
        self.assertEqual(args.command, "search")
        self.assertEqual(args.query, ["hello", "world"])
        self.assertEqual(args.limit, 20)
        self.assertFalse(args.verbose)
        self.assertFalse(args.json)

    def test_search_with_options(self):
        args = self.parser.parse_args([
            "search", "query", "-n", "5", "-v", "-j", "-s", "/scope",
        ])
        self.assertEqual(args.limit, 5)
        self.assertTrue(args.verbose)
        self.assertTrue(args.json)
        self.assertEqual(args.scope, "/scope")

    def test_status_subcommand(self):
        args = self.parser.parse_args(["status"])
        self.assertEqual(args.command, "status")

    def test_watch_subcommand(self):
        args = self.parser.parse_args(["watch"])
        self.assertEqual(args.command, "watch")
        self.assertEqual(args.path, ".")

    def test_config_subcommand_no_args(self):
        args = self.parser.parse_args(["config"])
        self.assertEqual(args.command, "config")
        self.assertIsNone(args.key)
        self.assertIsNone(args.value)

    def test_config_with_key(self):
        args = self.parser.parse_args(["config", "some_key"])
        self.assertEqual(args.key, "some_key")
        self.assertIsNone(args.value)

    def test_config_with_key_and_value(self):
        args = self.parser.parse_args(["config", "some_key", "some_value"])
        self.assertEqual(args.key, "some_key")
        self.assertEqual(args.value, "some_value")

    def test_no_subcommand(self):
        args = self.parser.parse_args([])
        self.assertIsNone(args.command)


# ---------------------------------------------------------------------------
# _format_size tests
# ---------------------------------------------------------------------------

class TestFormatSize(unittest.TestCase):
    """Tests for the _format_size helper."""

    def test_zero_bytes(self):
        self.assertEqual(_format_size(0), "0 B")

    def test_small_bytes(self):
        self.assertEqual(_format_size(512), "512 B")

    def test_one_byte(self):
        self.assertEqual(_format_size(1), "1 B")

    def test_exactly_1023_bytes(self):
        self.assertEqual(_format_size(1023), "1023 B")

    def test_kibibytes(self):
        # 1024 bytes -> 1 KiB
        result = _format_size(1024)
        self.assertIn("KiB", result)

    def test_mebibytes(self):
        # 1024 * 1024 = 1048576 bytes -> 1 MiB
        result = _format_size(1024 * 1024)
        self.assertIn("MiB", result)

    def test_gibibytes(self):
        # 1024^3 bytes -> 1 GiB
        result = _format_size(1024 ** 3)
        self.assertIn("GiB", result)


# ---------------------------------------------------------------------------
# main() tests
# ---------------------------------------------------------------------------

class TestMain(unittest.TestCase):
    """Tests for the main entry point."""

    def test_no_args_returns_zero(self):
        """main with no args prints help and returns 0."""
        rc = main([])
        self.assertEqual(rc, 0)


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