from pathlib import Path

import pytest

from l4d2host.paths import (
    get_left4me_root,
    overlay_path,
    validate_instance_name,
    validate_overlay_ref,
)


def test_get_left4me_root_defaults_to_var_lib_left4me(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.delenv("LEFT4ME_ROOT", raising=False)

    assert get_left4me_root() == Path("/var/lib/left4me")


def test_get_left4me_root_uses_env(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
    monkeypatch.setenv("LEFT4ME_ROOT", str(tmp_path))

    assert get_left4me_root() == tmp_path


def test_get_left4me_root_rejects_relative_env(monkeypatch: pytest.MonkeyPatch) -> None:
    monkeypatch.setenv("LEFT4ME_ROOT", "var/lib/left4me")

    with pytest.raises(ValueError):
        get_left4me_root()


@pytest.mark.parametrize("raw", ["", "   "])
def test_get_left4me_root_rejects_empty_env(monkeypatch: pytest.MonkeyPatch, raw: str) -> None:
    monkeypatch.setenv("LEFT4ME_ROOT", raw)

    with pytest.raises(ValueError):
        get_left4me_root()


@pytest.mark.parametrize("ref", ["standard", "competitive/base", "users/42/custom"])
def test_validate_overlay_ref_accepts_safe_refs(ref: str) -> None:
    assert validate_overlay_ref(ref) == ref


@pytest.mark.parametrize(
    "ref",
    ["", "/tmp/bad", "../bad", "bad/../evil", "bad//evil", " bad", "bad ", ".", "bad/./evil"],
)
def test_validate_overlay_ref_rejects_unsafe_refs(ref: str) -> None:
    with pytest.raises(ValueError):
        validate_overlay_ref(ref)


@pytest.mark.parametrize("name", ["srv1", "alpha", "my-server", "srv_01", "a", "a" * 64])
def test_validate_instance_name_accepts_safe_names(name: str) -> None:
    assert validate_instance_name(name) == name


@pytest.mark.parametrize(
    "name",
    [
        "",
        " ",
        "..",
        ".",
        "../foo",
        "foo/..",
        "foo/bar",
        "foo\\bar",
        " foo",
        "foo ",
        "Foo",
        "foo bar",
        "foo$",
        "-foo",
        "_foo",
        "foo@bar",
        "a" * 65,
    ],
)
def test_validate_instance_name_rejects_unsafe_names(name: str) -> None:
    with pytest.raises(ValueError):
        validate_instance_name(name)


def test_overlay_path_resolves_under_root(tmp_path: Path) -> None:
    assert overlay_path("standard", root=tmp_path) == tmp_path / "overlays" / "standard"


def test_overlay_path_rejects_symlink_escape(tmp_path: Path) -> None:
    outside = tmp_path / "outside"
    outside.mkdir()
    overlays = tmp_path / "overlays"
    overlays.mkdir()
    (overlays / "escape").symlink_to(outside)

    with pytest.raises(ValueError):
        overlay_path("escape", root=tmp_path)
