<script lang="ts">
  import TreeNode from "./TreeNode.svelte";
  import { api } from "./api.js";
  import { expanded, currentNode, breadcrumb, toggleExpanded, treeVersion } from "./browser.js";
  import { toastErr } from "./stores.js";
  import type { BreadcrumbEntry, NodeChild, NodeDetail } from "./types.js";

  let { node, depth }: { node: NodeChild; depth: number } = $props();

  let children = $state<NodeChild[] | null>(null);
  const isOpen = $derived($expanded.has(node.id));
  const isSelected = $derived($currentNode?.id === node.id);

  // 树刷新信号(增/删/移/重命名)→ 失效子节点缓存,展开状态下随之重载
  $effect(() => {
    void $treeVersion;
    children = null;
  });

  $effect(() => {
    if (isOpen && node.kind === "FOLDER" && children === null) {
      api<{ nodes: NodeChild[] }>(`/database/api/nodes?parentId=${encodeURIComponent(node.id)}`)
        .then((r) => (children = r.nodes))
        .catch((e) => toastErr(e instanceof Error ? e.message : String(e)));
    }
  });

  async function select(): Promise<void> {
    if (node.kind === "FOLDER") toggleExpanded(node.id);
    try {
      const [detail, crumb] = await Promise.all([
        api<{ node: NodeDetail }>(`/database/api/nodes/${node.id}`),
        api<{ breadcrumb: BreadcrumbEntry[] }>(`/database/api/nodes/${node.id}/breadcrumb`),
      ]);
      currentNode.set(detail.node);
      breadcrumb.set(crumb.breadcrumb);
    } catch (e) {
      toastErr(e instanceof Error ? e.message : String(e));
    }
  }
</script>

<div>
  <div
    class="tree-item flex cursor-pointer items-center gap-1 rounded-lg px-1.5 py-1.5 select-none {isSelected ? 'bg-selected' : 'hover:bg-hover'}"
    role="button"
    tabindex="0"
    onclick={select}
    onkeydown={(e) => e.key === "Enter" && select()}
  >
    <span class="flex h-4 w-4 shrink-0 items-center justify-center text-ink-3">
      {#if node.kind === "FOLDER"}
        <svg width="9" height="9" viewBox="0 0 24 24" fill="currentColor">
          {#if isOpen}<path d="M6 9l6 6 6-6z" />{:else}<path d="M9 6l6 6-6 6z" />{/if}
        </svg>
      {/if}
    </span>
    <span class="flex h-4 w-4 shrink-0 items-center justify-center {node.kind === 'PROJECT' ? 'text-ink' : 'text-ink-3'}">
      {#if node.kind === "PROJECT"}
        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" /></svg>
      {:else}
        <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7Z" /></svg>
      {/if}
    </span>
    <span class="truncate">{node.name}</span>
    {#if node.role !== "MANAGE"}
      <span class="ml-auto pr-1 font-mono text-[10px] text-ink-3">{node.role}</span>
    {/if}
  </div>

  {#if node.kind === "FOLDER" && isOpen}
    <div class="ml-[15px] border-l border-guide pl-1">
      {#if children === null}
        <div class="px-3 py-1.5 text-xs text-ink-3">…</div>
      {:else}
        {#each children as child (child.id)}
          <TreeNode node={child} depth={depth + 1} />
        {/each}
      {/if}
    </div>
  {/if}
</div>
