"""Tests.tests.unit.presentation.cli.test_cli_adapter
Where: Automated test module.
What: Contains test cases verifying project behaviour.
Why: Ensures regressions are caught and documented.
"""

import sys
import types

import pytest


def _install_stub_mcp_module(funcs: dict[str, object]) -> None:
    """Install a stub for mcp_servers.noveler.main into sys.modules.

    The stub prevents importing the real, heavy MCP module during unit tests.
    """
    pkg = types.ModuleType("mcp_servers")
    subpkg = types.ModuleType("mcp_servers.noveler")
    mod = types.ModuleType("mcp_servers.noveler.main")

    for name, obj in funcs.items():
        setattr(mod, name, obj)

    # Link modules
    subpkg.main = mod
    pkg.noveler = subpkg

    sys.modules["mcp_servers"] = pkg
    sys.modules["mcp_servers.noveler"] = subpkg
    sys.modules["mcp_servers.noveler.main"] = mod


@pytest.mark.unit
def test_mcp_call_unknown_tool_returns_2(monkeypatch: pytest.MonkeyPatch) -> None:
    from noveler.presentation.cli import cli_adapter

    async def dummy_exec(args):
        return {"success": True}

    # Install module without the requested tool (e.g., no execute_foo)
    _install_stub_mcp_module({"execute_run_quality_checks": dummy_exec})

    # Unknown tool
    rc = cli_adapter.run(["mcp", "call", "unknown_tool", "{}"])
    assert rc == 2


@pytest.mark.unit
def test_mcp_call_run_quality_checks_success(monkeypatch: pytest.MonkeyPatch) -> None:
    from noveler.presentation.cli import cli_adapter

    async def exec_rqc(args):
        return {"success": True, "score": 85}

    _install_stub_mcp_module({"execute_run_quality_checks": exec_rqc})

    rc = cli_adapter.run(["mcp", "call", "run_quality_checks", '{"episode_number": 1}'])
    assert rc == 0


@pytest.mark.unit
def test_check_command_success_exit_code(monkeypatch: pytest.MonkeyPatch) -> None:
    from noveler.presentation.cli import cli_adapter

    async def exec_rqc(args):
        # Return a score above threshold so exit code is 0
        return {"success": True, "score": 82.5}

    async def exec_fix(args):
        return {"success": True, "metadata": {"applied": 3}}

    _install_stub_mcp_module(
        {
            "execute_run_quality_checks": exec_rqc,
            "execute_fix_quality_issues": exec_fix,
        }
    )

    rc = cli_adapter.run(["check", "1"])  # no --auto-fix path
    assert rc == 0


@pytest.mark.unit
def test_ddd_validate_command(
    tmp_path,
    capsys: pytest.CaptureFixture[str],
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    from noveler.presentation.cli import cli_adapter

    class DummyConsole:
        def __init__(self) -> None:
            self.lines: list[str] = []

        def print(self, *args, **kwargs) -> None:
            message = " ".join(str(arg) for arg in args)
            self.lines.append(message)

        def print_warning(self, message: str) -> None:
            self.print(message)

        def print_info(self, message: str) -> None:
            self.print(message)

        def print_success(self, message: str) -> None:
            self.print(message)

        def print_error(self, message: str) -> None:
            self.print(message)

    dummy_console = DummyConsole()
    monkeypatch.setattr(cli_adapter, "get_console", lambda: dummy_console)

    project = tmp_path / "sample_project"
    domain_dir = project / "domain"
    domain_dir.mkdir(parents=True, exist_ok=True)
    (domain_dir / "__init__.py").write_text("", encoding="utf-8")
    (domain_dir / "entities.py").write_text(
        "class Episode:\n    def publish(self):\n        return True\n",
        encoding="utf-8",
    )

    rc = cli_adapter.run(["ddd", "validate", f"--path={project}", "--threshold=70"])
    captured = capsys.readouterr()
    combined_output = captured.out + captured.err
    full_output = "\n".join(dummy_console.lines + [combined_output])
    assert "DDD Validation Results" in full_output
    assert rc == 0
