"""CLI parsing and validation for --competitors / --competitors-list."""

from __future__ import annotations

import io
import unittest
from contextlib import redirect_stderr

import last30days as cli


def _parse(*argv: str):
    parser = cli.build_parser()
    args, _extra = parser.parse_known_args(argv)
    return args


class CompetitorsCliTests(unittest.TestCase):
    def test_flag_absent_returns_disabled(self):
        args = _parse("Kanye West")
        enabled, count, explicit = cli.resolve_competitors_args(args)
        self.assertFalse(enabled)
        self.assertEqual(count, 0)
        self.assertEqual(explicit, [])

    def test_bare_flag_defaults_to_two(self):
        args = _parse("Kanye West", "--competitors")
        enabled, count, explicit = cli.resolve_competitors_args(args)
        self.assertTrue(enabled)
        self.assertEqual(count, 2)
        self.assertEqual(explicit, [])

    def test_explicit_three_still_supported(self):
        args = _parse("OpenAI", "--competitors", "3")
        enabled, count, _explicit = cli.resolve_competitors_args(args)
        self.assertTrue(enabled)
        self.assertEqual(count, 3)

    def test_explicit_count(self):
        args = _parse("OpenAI", "--competitors", "4")
        enabled, count, explicit = cli.resolve_competitors_args(args)
        self.assertTrue(enabled)
        self.assertEqual(count, 4)
        self.assertEqual(explicit, [])

    def test_explicit_list_preferred_over_discovery(self):
        args = _parse(
            "OpenAI",
            "--competitors",
            "--competitors-list",
            "Anthropic,xAI,Google Gemini",
        )
        enabled, count, explicit = cli.resolve_competitors_args(args)
        self.assertTrue(enabled)
        self.assertEqual(count, 3)
        self.assertEqual(explicit, ["Anthropic", "xAI", "Google Gemini"])

    def test_explicit_list_without_flag_implies_enabled(self):
        args = _parse("OpenAI", "--competitors-list", "Anthropic,xAI")
        enabled, count, explicit = cli.resolve_competitors_args(args)
        self.assertTrue(enabled)
        self.assertEqual(count, 2)
        self.assertEqual(explicit, ["Anthropic", "xAI"])

    def test_list_whitespace_normalized(self):
        args = _parse("OpenAI", "--competitors-list", " Anthropic , xAI ,  Gemini ")
        _enabled, count, explicit = cli.resolve_competitors_args(args)
        self.assertEqual(count, 3)
        self.assertEqual(explicit, ["Anthropic", "xAI", "Gemini"])

    def test_zero_count_rejected(self):
        args = _parse("Topic", "--competitors", "0")
        with self.assertRaises(SystemExit) as cm, redirect_stderr(io.StringIO()) as err:
            cli.resolve_competitors_args(args)
        self.assertEqual(cm.exception.code, 2)
        self.assertIn("--competitors must be >= 1", err.getvalue())

    def test_negative_count_rejected(self):
        args = _parse("Topic", "--competitors", "-1")
        with self.assertRaises(SystemExit), redirect_stderr(io.StringIO()):
            cli.resolve_competitors_args(args)

    def test_over_max_count_clamps_with_warning(self):
        args = _parse("Topic", "--competitors", "99")
        err = io.StringIO()
        with redirect_stderr(err):
            enabled, count, explicit = cli.resolve_competitors_args(args)
        self.assertTrue(enabled)
        self.assertEqual(count, cli.COMPETITORS_MAX)
        self.assertEqual(explicit, [])
        self.assertIn("clamping", err.getvalue())

    def test_overlong_list_clamps_with_warning(self):
        args = _parse(
            "Topic",
            "--competitors-list",
            "A,B,C,D,E,F,G,H",
        )
        err = io.StringIO()
        with redirect_stderr(err):
            enabled, count, explicit = cli.resolve_competitors_args(args)
        self.assertTrue(enabled)
        self.assertEqual(count, cli.COMPETITORS_MAX)
        self.assertEqual(len(explicit), cli.COMPETITORS_MAX)
        self.assertIn("clamping to", err.getvalue())

    def test_list_count_mismatch_warns(self):
        args = _parse(
            "Topic",
            "--competitors",
            "5",
            "--competitors-list",
            "A,B",
        )
        err = io.StringIO()
        with redirect_stderr(err):
            enabled, count, explicit = cli.resolve_competitors_args(args)
        self.assertTrue(enabled)
        self.assertEqual(count, 2)
        self.assertEqual(explicit, ["A", "B"])
        self.assertIn("--competitors=5 ignored", err.getvalue())

    def test_empty_list_rejected(self):
        args = _parse("Topic", "--competitors-list", ",,  ,")
        with self.assertRaises(SystemExit) as cm, redirect_stderr(io.StringIO()):
            cli.resolve_competitors_args(args)
        self.assertEqual(cm.exception.code, 2)

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