from io import StringIO
from pathlib import Path

import pytest
from arcade_cli.new import create_new_toolkit, create_new_toolkit_minimal
from rich.console import Console


def test_create_new_toolkit_prints_next_steps(tmp_path: Path) -> None:
    """create_new_toolkit (full template) should print numbered next steps."""
    output_dir = tmp_path / "full_test"
    output_dir.mkdir()

    buf = StringIO()
    test_console = Console(file=buf, force_terminal=False)
    import arcade_cli.new as new_mod

    orig = new_mod.console
    new_mod.console = test_console
    try:
        create_new_toolkit(str(output_dir), "my_server")
    finally:
        new_mod.console = orig

    output = buf.getvalue()
    assert "Next steps:" in output
    assert "1. cd " in output
    assert "make install" in output
    assert "make dev" in output
    assert "make test" in output
    assert "my_server" in output


def test_create_new_toolkit_full_template_matches_monorepo(tmp_path: Path) -> None:
    """Full template should produce files matching monorepo conventions."""
    output_dir = tmp_path / "full_conventions"
    output_dir.mkdir()

    buf = StringIO()
    test_console = Console(file=buf, force_terminal=False)
    import arcade_cli.new as new_mod

    orig = new_mod.console
    new_mod.console = test_console
    try:
        create_new_toolkit(str(output_dir), "my_server")
    finally:
        new_mod.console = orig

    toolkit_dir = output_dir / "my_server"

    # pyproject.toml formatting checks
    pyproject = (toolkit_dir / "pyproject.toml").read_text()
    assert 'requires = ["hatchling"]' in pyproject
    assert 'license = { text = "Proprietary' in pyproject
    assert 'asyncio_mode = "auto"' in pyproject
    assert "disallow_untyped_defs = true" in pyproject
    assert '"True"' not in pyproject

    # Makefile should not have pre-commit install
    makefile = (toolkit_dir / "Makefile").read_text()
    assert "pre-commit install" not in makefile


def test_create_new_toolkit_minimal_with_spaces(tmp_path: Path) -> None:
    output_dir = tmp_path / "dir with spaces"
    output_dir.mkdir()

    create_new_toolkit_minimal(str(output_dir), "my_server")

    server_root = output_dir / "my_server"
    assert (server_root / "pyproject.toml").is_file()
    assert (server_root / "src" / "my_server" / "server.py").is_file()
    assert (server_root / ".env.example").is_file()


def test_create_new_toolkit_minimal_prints_next_steps(tmp_path: Path) -> None:
    """After scaffolding, the CLI should print 'Next steps' guidance."""
    output_dir = tmp_path / "scaffold_test"
    output_dir.mkdir()

    # Capture console output by replacing the module-level console.
    buf = StringIO()
    test_console = Console(file=buf, force_terminal=False)

    import arcade_cli.new as new_mod

    orig = new_mod.console
    new_mod.console = test_console
    try:
        create_new_toolkit_minimal(str(output_dir), "demo_srv")
    finally:
        new_mod.console = orig

    output = buf.getvalue()
    assert "Next steps:" in output, f"Expected 'Next steps:' in output:\n{output}"
    assert "1. cd " in output, f"Expected numbered step 1 in output:\n{output}"
    assert "2. Run the server (choose one transport):" in output, (
        f"Expected numbered step 2 in output:\n{output}"
    )
    assert "- stdio: uv run server.py" in output, f"Expected stdio option in output:\n{output}"
    assert "- http:  uv run server.py --transport http --port 8000" in output, (
        f"Expected HTTP option in output:\n{output}"
    )
    assert "uv run server.py" in output, f"Expected 'uv run server.py' in output:\n{output}"
    assert "demo_srv" in output, f"Expected toolkit name in output:\n{output}"


def test_create_new_toolkit_minimal_rejects_duplicate(tmp_path: Path) -> None:
    """Creating a toolkit with a name that already exists should raise."""
    output_dir = tmp_path / "dup_test"
    output_dir.mkdir()

    create_new_toolkit_minimal(str(output_dir), "my_srv")

    with pytest.raises(FileExistsError, match="already exists"):
        create_new_toolkit_minimal(str(output_dir), "my_srv")


def test_create_new_toolkit_minimal_rejects_invalid_name(tmp_path: Path) -> None:
    """Toolkit names with invalid characters should raise ValueError."""
    output_dir = tmp_path / "invalid_test"
    output_dir.mkdir()

    with pytest.raises(ValueError, match="illegal characters"):
        create_new_toolkit_minimal(str(output_dir), "My-Server!")
