import json

from scout.detect import inspect


def make(tmp_path, files: dict[str, str]):
    for name, body in files.items():
        p = tmp_path / name
        p.parent.mkdir(parents=True, exist_ok=True)
        p.write_text(body)
    return tmp_path


def test_a_node_project(tmp_path):
    make(tmp_path, {
        "package.json": json.dumps({"scripts": {"test": "vitest run", "typecheck": "tsc --noEmit"}}),
        "package-lock.json": "{}",
        "README.md": "# app",
    })
    found = inspect(tmp_path)
    assert found.test_command == "npm test"
    assert found.extra_checks == ["npm run typecheck"]
    assert found.install_hint == "npm ci"
    assert found.link_dirs == ("node_modules",)
    assert found.context_files == ["README.md"]


def test_the_placeholder_npm_writes_into_every_project_is_not_mistaken_for_tests(tmp_path):
    make(tmp_path, {"package.json": json.dumps(
        {"scripts": {"test": 'echo "Error: no test specified" && exit 1'}})})
    assert inspect(tmp_path).test_command == ""


def test_the_right_installer_for_the_lock_file(tmp_path):
    make(tmp_path, {"package.json": json.dumps({"scripts": {"test": "jest"}}), "pnpm-lock.yaml": ""})
    assert inspect(tmp_path).install_hint == "pnpm install --frozen-lockfile"


def test_a_project_with_more_than_one_part(tmp_path):
    make(tmp_path, {
        "package.json": json.dumps({"scripts": {"test": "jest"}, "workspaces": ["web"]}),
        "web/package.json": "{}",
    })
    assert inspect(tmp_path).link_dirs == ("node_modules", "web/node_modules")


def test_a_python_project_with_uv(tmp_path):
    make(tmp_path, {"pyproject.toml": '[tool.pytest.ini_options]\ntestpaths = ["tests"]\n',
                    "uv.lock": "", "tests/test_x.py": ""})
    found = inspect(tmp_path)
    assert found.test_command == "uv run pytest -q" and found.install_hint == "uv sync"


def test_a_python_project_with_its_own_environment(tmp_path):
    make(tmp_path, {"pyproject.toml": '[tool.pytest.ini_options]\n', "tests/test_x.py": ""})
    (tmp_path / ".venv" / "bin").mkdir(parents=True)
    (tmp_path / ".venv" / "bin" / "python").write_text("")
    assert inspect(tmp_path).test_command == ".venv/bin/python -m pytest -q"


def test_a_makefile(tmp_path):
    make(tmp_path, {"Makefile": "build:\n\techo hi\ntest:\n\techo test\n"})
    assert "make test" in inspect(tmp_path).test_commands


def test_the_other_languages(tmp_path):
    assert inspect(make(tmp_path / "r", {"Cargo.toml": ""})).test_command == "cargo test"
    assert inspect(make(tmp_path / "g", {"go.mod": "module x"})).test_command == "go test ./..."
    assert inspect(make(tmp_path / "e", {"mix.exs": ""})).test_command == "mix test"
    rb = make(tmp_path / "rb", {"Gemfile": "", "spec/a_spec.rb": ""})
    assert inspect(rb).test_command == "bundle exec rspec"


def test_a_project_that_says_nothing_about_itself(tmp_path):
    found = inspect(make(tmp_path, {"notes.txt": "hello"}))
    assert found.test_commands == [] and found.test_command == ""
    assert found.deploy_command is None


def test_how_a_project_is_put_live(tmp_path):
    assert inspect(make(tmp_path / "f", {"fly.toml": ""})).deploy_command == "fly deploy --remote-only"
    assert inspect(make(tmp_path / "v", {"vercel.json": "{}"})).deploy_command == "vercel --prod"


def test_the_documents_worth_reading_are_found(tmp_path):
    make(tmp_path, {"README.md": "#", "CLAUDE.md": "#", "docs/DECISIONS.md": "x" * 500,
                    "docs/tiny.md": "x", "docs/BIG.md": "x" * 900})
    files = inspect(tmp_path).context_files
    assert files[:2] == ["CLAUDE.md", "README.md"]
    assert files[2:] == ["docs/BIG.md", "docs/DECISIONS.md"]      # biggest two, largest first
