"""ProjectManager self-heal: re-discover on-disk projects missing from the registry.

Guards the Modal-sandbox bug where the project registry lived on ephemeral
~/.pantheon, so a restart dropped every sub-project's entry while the directories
survived on the persistent Volume — leaving the PROJECTS list empty even though
the work was still on disk.
"""
from pathlib import Path

from pantheon.chatroom.projects import (
    ProjectManager,
    _friendly_default_name,
    _registry_path,
    _volume_root,
)


def test_volume_root_derivation():
    # The Volume root that contains a path (independent workspaces are its children).
    assert _volume_root("/workspace") == "/workspace"
    assert _volume_root("/workspace/default_workspace") == "/workspace"
    assert _volume_root("/workspace/other_ws/sub") == "/workspace"
    assert _volume_root("/__modal/volumes/vo-abc/default_workspace") == "/__modal/volumes/vo-abc"
    # Not on a Volume → None (local/desktop).
    assert _volume_root("/Users/me/project") is None
    assert _volume_root("/workspaces/foo") is None  # look-alike, not the mount


def test_registry_path_persists_on_volume_in_sandbox():
    # Sandbox: registry lives on the persistent Volume (survives restarts), keyed
    # to the Volume ROOT even when the workspace is a subdir.
    assert str(_registry_path("/workspace")) == "/workspace/.pantheon/projects.json"
    assert str(_registry_path("/workspace/default_workspace")) == "/workspace/.pantheon/projects.json"
    assert str(_registry_path("/__modal/volumes/vo-abc")) == "/__modal/volumes/vo-abc/.pantheon/projects.json"
    assert str(_registry_path("/__modal/volumes/vo-abc/sub")) == "/__modal/volumes/vo-abc/.pantheon/projects.json"
    # A look-alike path is NOT the Volume.
    assert "/workspaces/" not in str(_registry_path("/workspaces/foo"))


def test_registry_path_local_stays_global(tmp_path, monkeypatch):
    monkeypatch.setenv("HOME", str(tmp_path))
    assert str(_registry_path("/Users/me/project")).startswith(str(tmp_path))
    assert str(_registry_path(None)).startswith(str(tmp_path))


def test_friendly_default_name_hides_volume_id():
    # The Modal Volume root (mount alias or real path) → "Workspace", not the id.
    assert _friendly_default_name("/workspace") == "Workspace"
    assert _friendly_default_name("/workspace/") == "Workspace"
    assert _friendly_default_name("/__modal/volumes/vo-cEm8TSQpvrlRvld6ZXQdpm") == "Workspace"
    # Sub-projects and local/desktop paths keep their real, meaningful basename.
    assert _friendly_default_name("/workspace/metabolomics_analysis") == "metabolomics_analysis"
    assert _friendly_default_name("/__modal/volumes/vo-abc/sub") == "sub"
    assert _friendly_default_name("/workspace/default_workspace") == "default_workspace"
    assert _friendly_default_name("/Users/me/my_project") == "my_project"


def _make_workspace(root: Path) -> Path:
    ws = root / "workspace"
    (ws / ".pantheon").mkdir(parents=True)                       # root = default project
    (ws / "sub_a" / ".pantheon" / "memory").mkdir(parents=True)  # sub-project A (had chats)
    (ws / "sub_b" / ".pantheon").mkdir(parents=True)             # sub-project B
    (ws / "not_a_project").mkdir()                               # no marker → not a project
    (ws / ".hidden" / ".pantheon").mkdir(parents=True)           # hidden → never a project
    return ws


def test_discovers_orphaned_subprojects(tmp_path, monkeypatch):
    monkeypatch.setenv("HOME", str(tmp_path / "home"))  # registry → temp, not real ~
    ws = _make_workspace(tmp_path)

    pm = ProjectManager(active_path=str(ws))
    names = {p["name"] for p in pm.list_projects()}

    assert {"sub_a", "sub_b"} <= names, f"orphaned sub-projects not recovered: {names}"
    assert "not_a_project" not in names, f"registered a dir with no .pantheon marker: {names}"
    assert ".hidden" not in names, f"registered a hidden dir: {names}"


def test_discovery_idempotent_across_restart(tmp_path, monkeypatch):
    monkeypatch.setenv("HOME", str(tmp_path / "home"))
    ws = _make_workspace(tmp_path)

    first = {p["name"] for p in ProjectManager(active_path=str(ws)).list_projects()}
    second = {p["name"] for p in ProjectManager(active_path=str(ws)).list_projects()}

    assert first == second, f"re-discovery not idempotent across restart: {first} vs {second}"
