"""Tests for complyform.cli.main."""

from __future__ import annotations

from unittest.mock import patch

import pytest
from typer.testing import CliRunner

from complyform.cli.main import app

runner = CliRunner()


class TestVersion:
    def test_version_flag(self) -> None:
        result = runner.invoke(app, ["--version"])
        assert result.exit_code == 0
        assert "complyform 0.1.0" in result.output


class TestHelp:
    def test_help_shows_panels(self) -> None:
        result = runner.invoke(app, ["--help"])
        assert result.exit_code == 0
        assert "Brownfield (Existing Infrastructure)" in result.output
        assert "Greenfield (New Infrastructure)" in result.output
        assert "Discovery" in result.output
        assert "Management" in result.output

    def test_help_lists_commands(self) -> None:
        result = runner.invoke(app, ["--help"])
        output = result.output
        for cmd in [
            "scan",
            "assess",
            "remediate",
            "fix",
            "explain",
            "validate",
            "report",
            "policy-gen",
            "export",
            "init",
            "generate",
            "frameworks",
            "config",
            "update",
            "dashboard",
            "doctor",
            "feedback",
        ]:
            assert cmd in output, f"'{cmd}' missing from help"

    def test_no_args_shows_help(self) -> None:
        result = runner.invoke(app, [])
        # no_args_is_help — output contains usage info
        assert "Usage" in result.output or "Brownfield" in result.output


class TestMutualExclusivity:
    def test_verbose_and_quiet(self) -> None:
        result = runner.invoke(app, ["--verbose", "--quiet", "scan"])
        assert result.exit_code != 0


class TestErrorHandling:
    def test_keyboard_interrupt(self) -> None:
        from complyform.cli.main import main

        with patch(
            "complyform.cli.main.app",
            side_effect=KeyboardInterrupt,
        ):
            with pytest.raises(SystemExit) as exc_info:
                main()
            assert exc_info.value.code == 130

    def test_unexpected_exception(self) -> None:
        from complyform.cli.main import main

        with patch(
            "complyform.cli.main.app",
            side_effect=RuntimeError("boom"),
        ):
            with pytest.raises(SystemExit) as exc_info:
                main()
            assert exc_info.value.code == 2

    def test_complyform_error_exit_code(self) -> None:
        from complyform.cli.main import main
        from complyform.core.errors import ComplyFormError

        with patch(
            "complyform.cli.main.app",
            side_effect=ComplyFormError(title="Test", message="msg", fix="fix"),
        ):
            with pytest.raises(SystemExit) as exc_info:
                main()
            assert exc_info.value.code == 2


class TestStubCommands:
    @pytest.mark.parametrize(
        "cmd",
        [
            "scan",
            "assess",
            "explain",
            "report",
            "policy-gen",
            "export",
            "init",
            "generate",
            "frameworks",
            "config",
            "dashboard",
        ],
    )
    def test_stub_raises(self, cmd: str) -> None:
        result = runner.invoke(app, [cmd])
        assert result.exit_code != 0
