"""Tests for #4226 — symlinks in the workspace file tree must display correctly.

The renderer _renderTreeItems must use isDirLike (type==='dir' || (type==='symlink'
&& is_dir)) for all expand/navigate/delete gates rather than type==='dir' alone.
"""
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parents[1]
UI_JS = (REPO_ROOT / "static" / "ui.js").read_text(encoding="utf-8")
ICONS_JS = (REPO_ROOT / "static" / "icons.js").read_text(encoding="utf-8")
I18N_JS = (REPO_ROOT / "static" / "i18n.js").read_text(encoding="utf-8")
WS_JS = (REPO_ROOT / "static" / "workspace.js").read_text(encoding="utf-8")


def _render_block() -> str:
    start = UI_JS.find("function _renderTreeItems(container, entries, depth)")
    assert start >= 0, "_renderTreeItems not found in static/ui.js"
    # Capture to end of function (next top-level async/function declaration)
    end = UI_JS.find("\nasync function deleteWorkspaceDir", start)
    assert end >= 0, "end of _renderTreeItems not found"
    return UI_JS[start:end]


class TestIsDirLikeLocals:
    def test_isLk_local_declared(self):
        block = _render_block()
        assert "const isLk = item.type === 'symlink';" in block, \
            "isLk local must be declared inside the per-item loop"

    def test_isExternalLink_local_declared(self):
        block = _render_block()
        assert "const isExternalLink = isLk && item.target_outside_workspace;" in block, \
            "isExternalLink local must be declared for display-only external symlinks"

    def test_isDirLike_local_declared(self):
        block = _render_block()
        assert "const isDirLike = !isExternalLink && (item.type === 'dir' || (isLk && item.is_dir));" in block, \
            "isDirLike local must be declared inside the per-item loop"

    def test_isFileLike_local_declared(self):
        block = _render_block()
        assert "const isFileLike = !isExternalLink && !isDirLike;" in block, \
            "isFileLike local must be declared for file-like symlink handling"

    def test_wsIsDir_dataset_set(self):
        block = _render_block()
        assert "el.dataset.wsIsDir = String(isDirLike);" in block, \
            "data-ws-is-dir must be set on every file-item row"


class TestExpandToggle:
    def test_toggle_uses_isDirLike(self):
        block = _render_block()
        assert "if(isDirLike){" in block, \
            "expand toggle must branch on isDirLike, not item.type==='dir'"

    def test_recursive_render_uses_isDirLike(self):
        block = _render_block()
        assert "if(isDirLike&&S._expandedDirs.has(item.path)){" in block, \
            "recursive child render must branch on isDirLike"


class TestLinkIcon:
    def test_link_icon_path_exists(self):
        assert "'link':" in ICONS_JS, \
            "'link' key must be added to LI_PATHS in static/icons.js"

    def test_icon_dispatch_uses_li_link(self):
        block = _render_block()
        assert "li('link', 14)" in block, \
            "icon dispatch must emit li('link', 14) for symlink rows"

    def test_external_link_icon_path_exists(self):
        assert "'external-link':" in ICONS_JS, \
            "'external-link' key must be in LI_PATHS for display-only external symlinks"

    def test_icon_dispatch_uses_li_external_link(self):
        block = _render_block()
        assert "li('external-link', 14)" in block, \
            "icon dispatch must emit li('external-link', 14) for external symlink rows"


class TestSymlinkTooltip:
    def test_symlink_link_to_key_in_i18n(self):
        count = I18N_JS.count("symlink_link_to:")
        assert count >= 5, \
            f"symlink_link_to key must appear in multiple locale blocks; found {count}"

    def test_elideMiddle_utility_present(self):
        assert "function elideMiddle(" in UI_JS, \
            "elideMiddle() utility must be defined in static/ui.js"

    def test_tooltip_uses_symlink_link_to(self):
        block = _render_block()
        assert "t('symlink_link_to')" in block, \
            "symlink rows must set a tooltip using the symlink_link_to i18n key"


class TestDragDropGuard:
    def test_workspace_drag_guard_widened(self):
        assert '[data-ws-is-dir="true"]' in WS_JS, \
            "workspace.js drag-over guard must also exclude [data-ws-is-dir='true'] rows"


class TestSymlinkFileAffordances:
    def test_size_badge_uses_isFileLike(self):
        block = _render_block()
        assert "if(isFileLike&&item.size){" in block, \
            "symlink-to-file rows must render the file-size badge"

    def test_delete_button_uses_isFileLike(self):
        block = _render_block()
        assert "if(isFileLike){" in block, \
            "symlink-to-file rows must render the inline delete button"
