<script lang="ts">
  import { Check, ChevronDown, ChevronRight, Folder, FolderOpen, GitBranch, GitCompare, GitMerge, HardDrive, Pencil, Plus, Tag as TagIcon, Trash2, Upload, X } from "@lucide/svelte";
  import { tick } from "svelte";
  import type { GitBranch as GitBranchInfo, GitTag } from "../types";

  type BranchTreeNode = BranchFolderNode | BranchLeafNode;

  interface BranchFolderNode {
    kind: "folder";
    id: string;
    name: string;
    children: BranchTreeNode[];
    branchCount: number;
    current: boolean;
    branches: GitBranchInfo[];
    folders: Map<string, BranchFolderNode>;
  }

  interface BranchLeafNode {
    kind: "branch";
    id: string;
    branch: GitBranchInfo;
    displayName: string;
  }

  type BranchRow = BranchFolderRow | BranchLeafRow;

  interface BranchFolderRow {
    kind: "folder";
    id: string;
    name: string;
    depth: number;
    branchCount: number;
    current: boolean;
    branches: GitBranchInfo[];
  }

  interface BranchLeafRow {
    kind: "branch";
    id: string;
    branch: GitBranchInfo;
    displayName: string;
    depth: number;
    scopeLabel: string;
  }

  interface Props {
    branches: GitBranchInfo[];
    localBranches: GitBranchInfo[];
    remoteBranches: GitBranchInfo[];
    tags: GitTag[];
    hasRepository: boolean;
    isBusy: boolean;
    onCheckout: (branch: GitBranchInfo) => void;
    onCompareBranch: (branch: GitBranchInfo) => void;
    onMerge: (branch: GitBranchInfo) => void;
    onRebase: (branch: GitBranchInfo) => void;
    onCreateBranch: (branchName: string) => void | Promise<void>;
    onRenameBranch: (branch: GitBranchInfo) => void | Promise<void>;
    onDeleteBranch: (branch: GitBranchInfo) => void | Promise<void>;
    onDeleteRemoteBranch: (branch: GitBranchInfo) => void | Promise<void>;
    onDeleteBranchFolder: (folderName: string, branches: GitBranchInfo[], depth: number) => void | Promise<void>;
    onCreateTag: (name: string, message: string) => void | Promise<void>;
    onDeleteTag: (tag: GitTag) => void | Promise<void>;
    onPushTag: (tag: GitTag) => void | Promise<void>;
    onManageWorktrees: () => void;
    onCreateWorktree: (branch: GitBranchInfo) => void | Promise<void>;
    collapsed?: boolean;
    onToggleCollapsed?: () => void;
  }

  let {
    branches = [],
    localBranches = [],
    remoteBranches = [],
    tags = [],
    hasRepository = false,
    isBusy = false,
    onCheckout = () => {},
    onCompareBranch = () => {},
    onMerge = () => {},
    onRebase = () => {},
    onCreateBranch = () => {},
    onRenameBranch = () => {},
    onDeleteBranch = () => {},
    onDeleteRemoteBranch = () => {},
    onDeleteBranchFolder = () => {},
    onCreateTag = () => {},
    onDeleteTag = () => {},
    onPushTag = () => {},
    onManageWorktrees = () => {},
    onCreateWorktree = () => {},
    collapsed = false,
    onToggleCollapsed = () => {},
  }: Props = $props();

  let localOpen = $state(true);
  let remoteOpen = $state(false);
  let tagsOpen = $state(false);
  let createOpen = $state(false);
  let newBranchName = $state("");
  let createInput = $state<HTMLInputElement | null>(null);
  let tagCreateOpen = $state(false);
  let newTagName = $state("");
  let newTagMessage = $state("");
  let tagCreateInput = $state<HTMLInputElement | null>(null);
  let contextBranch = $state<GitBranchInfo | null>(null);
  let contextFolder = $state<BranchFolderRow | null>(null);
  let branchContextMenuElement = $state<HTMLElement | null>(null);
  let contextMenuX = $state(0);
  let contextMenuY = $state(0);
  let contextTag = $state<GitTag | null>(null);
  let tagContextMenuElement = $state<HTMLElement | null>(null);
  let tagContextMenuX = $state(0);
  let tagContextMenuY = $state(0);
  let collapsedBranchFolders = $state<Set<string>>(new Set());

  let localBranchRows = $derived(buildBranchRows("local", localBranches, "local"));
  let remoteBranchRows = $derived(buildBranchRows("remote", remoteBranches, "remote"));

  function createFolder(id: string, name: string): BranchFolderNode {
    return {
      kind: "folder",
      id,
      name,
      children: [],
      branchCount: 0,
      current: false,
      branches: [],
      folders: new Map(),
    };
  }

  function buildBranchRows(scope: string, branchList: GitBranchInfo[], scopeLabel: string): BranchRow[] {
    const root = createFolder(`${scope}:root`, "");

    for (const branch of branchList) {
      const parts = branch.name.split("/").filter(Boolean);
      const displayName = parts.length > 0 ? parts[parts.length - 1] : branch.name;
      const folderParts = parts.slice(0, -1);
      let parent = root;

      for (let index = 0; index < folderParts.length; index += 1) {
        const folderName = folderParts[index];
        const folderPath = folderParts.slice(0, index + 1).join("/");
        let folder = parent.folders.get(folderName);

        if (!folder) {
          folder = createFolder(`${scope}:folder:${folderPath}`, folderName);
          parent.folders.set(folderName, folder);
          parent.children.push(folder);
        }

        folder.branchCount += 1;
        folder.current ||= branch.current;
        folder.branches.push(branch);
        parent = folder;
      }

      parent.children.push({
        kind: "branch",
        id: `${scope}:branch:${branch.name}`,
        branch,
        displayName,
      });
    }

    sortBranchNodes(root.children);

    const rows: BranchRow[] = [];
    flattenBranchNodes(root.children, rows, 0, scopeLabel);
    return rows;
  }

  function sortBranchNodes(nodes: BranchTreeNode[]) {
    nodes.sort((left, right) => {
      if (left.kind !== right.kind) return left.kind === "folder" ? -1 : 1;
      const leftName = left.kind === "folder" ? left.name : left.displayName;
      const rightName = right.kind === "folder" ? right.name : right.displayName;
      return leftName.localeCompare(rightName, undefined, { sensitivity: "base" });
    });

    for (const node of nodes) {
      if (node.kind === "folder") sortBranchNodes(node.children);
    }
  }

  function flattenBranchNodes(nodes: BranchTreeNode[], rows: BranchRow[], depth: number, scopeLabel: string) {
    for (const node of nodes) {
      if (node.kind === "folder") {
        rows.push({
          kind: "folder",
          id: node.id,
          name: node.name,
          depth,
          branchCount: node.branchCount,
          current: node.current,
          branches: node.branches,
        });

        if (isBranchFolderOpen(node.id)) {
          flattenBranchNodes(node.children, rows, depth + 1, scopeLabel);
        }
      } else {
        rows.push({
          kind: "branch",
          id: node.id,
          branch: node.branch,
          displayName: node.displayName,
          depth,
          scopeLabel,
        });
      }
    }
  }

  function isBranchFolderOpen(id: string) {
    return !collapsedBranchFolders.has(id);
  }

  function toggleBranchFolder(id: string) {
    const next = new Set(collapsedBranchFolders);
    if (next.has(id)) next.delete(id);
    else next.add(id);
    collapsedBranchFolders = next;
  }

  function openCreateForm() {
    if (!hasRepository || isBusy) return;
    createOpen = true;
    queueMicrotask(() => createInput?.focus());
  }

  function closeCreateForm() {
    createOpen = false;
    newBranchName = "";
  }

  async function submitCreate(event: SubmitEvent) {
    event.preventDefault();
    const value = newBranchName.trim();
    if (!value || !hasRepository || isBusy) return;
    await onCreateBranch(value);
    newBranchName = "";
    createOpen = false;
    localOpen = true;
  }

  function checkoutOnDoubleClick(event: MouseEvent, branch: GitBranchInfo) {
    if (branch.current || isBusy) return;
    const target = event.target instanceof HTMLElement ? event.target : null;
    if (target?.closest("button")) return;
    onCheckout(branch);
  }

  function fitContextMenuToViewport(element: HTMLElement | null, x: number, y: number) {
    const rect = element?.getBoundingClientRect();
    const width = rect?.width ?? 184;
    const height = rect?.height ?? 0;

    return {
      x: Math.max(8, Math.min(x + 2, window.innerWidth - width - 8)),
      y: Math.max(8, Math.min(y + 2, window.innerHeight - height - 8)),
    };
  }

  async function openBranchContextMenu(event: MouseEvent, branch: GitBranchInfo) {
    event.preventDefault();
    event.stopPropagation();
    if (isBusy) return;

    contextBranch = branch;
    contextMenuX = event.clientX + 2;
    contextMenuY = event.clientY + 2;
    await tick();
    if (contextBranch !== branch) return;

    const position = fitContextMenuToViewport(branchContextMenuElement, event.clientX, event.clientY);
    contextMenuX = position.x;
    contextMenuY = position.y;
  }

  async function openFolderContextMenu(event: MouseEvent, folder: BranchFolderRow) {
    event.preventDefault();
    event.stopPropagation();
    if (isBusy || (folder.depth === 0 && folder.branches.every((branch) => branch.remote))) return;

    contextFolder = folder;
    contextMenuX = event.clientX + 2;
    contextMenuY = event.clientY + 2;
    await tick();
    if (contextFolder !== folder) return;

    const position = fitContextMenuToViewport(branchContextMenuElement, event.clientX, event.clientY);
    contextMenuX = position.x;
    contextMenuY = position.y;
  }

  function closeBranchContextMenu() {
    contextBranch = null;
    contextFolder = null;
  }

  async function renameContextBranch() {
    const branch = contextBranch;
    if (!branch || isBusy) return;
    closeBranchContextMenu();
    await onRenameBranch(branch);
  }

  function compareContextBranch() {
    const branch = contextBranch;
    if (!branch || isBusy) return;
    closeBranchContextMenu();
    onCompareBranch(branch);
  }

  async function deleteContextBranch() {
    const branch = contextBranch;
    if (!branch || branch.current || isBusy) return;
    closeBranchContextMenu();
    if (branch.remote) await onDeleteRemoteBranch(branch); else await onDeleteBranch(branch);
  }

  async function deleteContextFolder() {
    const folder = contextFolder;
    if (!folder || isBusy || (folder.depth === 0 && folder.branches.every((branch) => branch.remote))) return;
    closeBranchContextMenu();
    await onDeleteBranchFolder(folder.name, folder.branches, folder.depth);
  }

  async function createContextWorktree() {
    const branch = contextBranch;
    closeBranchContextMenu();
    if (!branch) return;
    await onCreateWorktree(branch);
  }

  async function checkoutContextBranch() {
    const branch = contextBranch;
    if (!branch || branch.current || isBusy) return;
    closeBranchContextMenu();
    await onCheckout(branch);
  }

  async function mergeContextBranch() {
    const branch = contextBranch;
    if (!branch || branch.current || isBusy) return;
    closeBranchContextMenu();
    await onMerge(branch);
  }

  async function rebaseContextBranch() {
    const branch = contextBranch;
    if (!branch || branch.current || isBusy) return;
    closeBranchContextMenu();
    await onRebase(branch);
  }

  function openTagCreateForm() {
    if (!hasRepository || isBusy) return;
    tagCreateOpen = true;
    queueMicrotask(() => tagCreateInput?.focus());
  }

  function closeTagCreateForm() {
    tagCreateOpen = false;
    newTagName = "";
    newTagMessage = "";
  }

  async function submitCreateTag(event: SubmitEvent) {
    event.preventDefault();
    const name = newTagName.trim();
    if (!name || !hasRepository || isBusy) return;
    await onCreateTag(name, newTagMessage.trim());
    newTagName = "";
    newTagMessage = "";
    tagCreateOpen = false;
    tagsOpen = true;
  }

  async function openTagContextMenu(event: MouseEvent, tag: GitTag) {
    event.preventDefault();
    event.stopPropagation();
    if (isBusy) return;

    contextTag = tag;
    tagContextMenuX = event.clientX + 2;
    tagContextMenuY = event.clientY + 2;
    await tick();
    if (contextTag !== tag) return;

    const position = fitContextMenuToViewport(tagContextMenuElement, event.clientX, event.clientY);
    tagContextMenuX = position.x;
    tagContextMenuY = position.y;
  }

  function closeTagContextMenu() {
    contextTag = null;
  }

  async function pushContextTag() {
    const tag = contextTag;
    if (!tag || isBusy) return;
    closeTagContextMenu();
    await onPushTag(tag);
  }

  async function deleteContextTag() {
    const tag = contextTag;
    if (!tag || isBusy) return;
    closeTagContextMenu();
    await onDeleteTag(tag);
  }

  function closeAllContextMenus() {
    closeBranchContextMenu();
    closeTagContextMenu();
  }

  function handleWindowKeydown(event: KeyboardEvent) {
    if (event.key === "Escape") closeAllContextMenus();
  }
</script>

<svelte:window on:click={closeAllContextMenus} on:keydown={handleWindowKeydown} on:contextmenu|capture={closeAllContextMenus} />

<section class="panel branch-panel grid grid-rows-[auto_1fr] overflow-hidden" class:collapsed aria-label="Branches">
  <div class="section-head">
    <div>
      <span class="eyebrow">Branches</span>
      <h2 class="mt-0.5 text-ink text-base font-bold leading-tight">Refs</h2>
    </div>
    <div class="branch-head-actions">
      <button
        class="branch-create-toggle"
        type="button"
        onclick={openCreateForm}
        disabled={!hasRepository || isBusy}
        title="Create new branch"
        aria-label="Create new branch"
      >
        <Plus size={14} aria-hidden="true" />
      </button>
      <span class="pill pill-count">{branches.length}</span>
      <button
        class="branch-create-toggle panel-collapse-toggle"
        type="button"
        onclick={onToggleCollapsed}
        aria-expanded={!collapsed}
        title={collapsed ? "Expand branches" : "Collapse branches"}
        aria-label={collapsed ? "Expand branches panel" : "Collapse branches panel"}
      >
        {#if collapsed}
          <ChevronRight size={14} aria-hidden="true" />
        {:else}
          <ChevronDown size={14} aria-hidden="true" />
        {/if}
      </button>
    </div>
  </div>

  {#if collapsed}
    <!-- collapsed -->
  {:else if !hasRepository}
    <p class="blank-state">Open a repository to list branches.</p>
  {:else}
    <div class="branch-list overflow-auto p-2 flex flex-col gap-0">
      {#if createOpen}
        <form class="branch-create-form" onsubmit={submitCreate}>
          <GitBranch size={15} aria-hidden="true" />
          <input
            bind:this={createInput}
            bind:value={newBranchName}
            disabled={isBusy}
            autocomplete="off"
            spellcheck="false"
            placeholder="new-branch-name"
            aria-label="New branch name"
          />
          <button class="branch-create-action confirm" type="submit" disabled={isBusy || newBranchName.trim().length === 0} title="Create branch">
            <Check size={14} aria-hidden="true" />
          </button>
          <button class="branch-create-action" type="button" onclick={closeCreateForm} disabled={isBusy} title="Cancel">
            <X size={14} aria-hidden="true" />
          </button>
        </form>
      {/if}

      <div class="branch-group">
        <button
          class="branch-group-toggle"
          type="button"
          onclick={() => { localOpen = !localOpen; }}
          aria-expanded={localOpen}
        >
          {#if localOpen}
            <ChevronDown size={14} aria-hidden="true" />
          {:else}
            <ChevronRight size={14} aria-hidden="true" />
          {/if}
          <span>Local</span>
          <span class="branch-group-count">{localBranches.length}</span>
        </button>

        {#if localOpen}
          {#if localBranches.length === 0}
            <div class="branch-empty">No local branches.</div>
          {:else}
            {#each localBranchRows as row (row.id)}
              {#if row.kind === "folder"}
                <button
                  class="branch-folder-row"
                  class:current={row.current}
                  style={`--branch-indent: ${row.depth * 16}px;`}
                  type="button"
                  onclick={() => toggleBranchFolder(row.id)}
                  oncontextmenu={(event) => openFolderContextMenu(event, row)}
                  aria-expanded={isBranchFolderOpen(row.id)}
                  title={`${row.name} (${row.branchCount})`}
                >
                  {#if isBranchFolderOpen(row.id)}
                    <ChevronDown size={14} aria-hidden="true" />
                    <FolderOpen size={15} aria-hidden="true" />
                  {:else}
                    <ChevronRight size={14} aria-hidden="true" />
                    <Folder size={15} aria-hidden="true" />
                  {/if}
                  <span class="branch-folder-name">{row.name}</span>
                  <span class="branch-folder-count">{row.branchCount}</span>
                </button>
              {:else}
                <article
                  class="branch-row"
                  class:current={row.branch.current}
                  style={`--branch-indent: ${row.depth * 16}px;`}
                  ondblclick={(event) => checkoutOnDoubleClick(event, row.branch)}
                  oncontextmenu={(event) => openBranchContextMenu(event, row.branch)}
                  title={row.branch.current ? "Current branch" : row.branch.name}
                >
                  <div class="branch-info">
                    <GitBranch size={16} aria-hidden="true" />
                    <div>
                      <strong>{row.displayName}</strong>
                      <span>{row.scopeLabel}</span>
                    </div>
                  </div>
                  {#if row.branch.current}
                    <span class="pill pill-active">Current</span>
                  {/if}
                </article>
              {/if}
            {/each}
          {/if}
        {/if}
      </div>

      <div class="branch-group">
        <button
          class="branch-group-toggle"
          type="button"
          onclick={() => { remoteOpen = !remoteOpen; }}
          aria-expanded={remoteOpen}
        >
          {#if remoteOpen}
            <ChevronDown size={14} aria-hidden="true" />
          {:else}
            <ChevronRight size={14} aria-hidden="true" />
          {/if}
          <span>Remote</span>
          <span class="branch-group-count">{remoteBranches.length}</span>
        </button>

        {#if remoteOpen}
          {#if remoteBranches.length === 0}
            <div class="branch-empty">No remote branches.</div>
          {:else}
            {#each remoteBranchRows as row (row.id)}
              {#if row.kind === "folder"}
                <button
                  class="branch-folder-row"
                  class:current={row.current}
                  style={`--branch-indent: ${row.depth * 16}px;`}
                  type="button"
                  onclick={() => toggleBranchFolder(row.id)}
                  oncontextmenu={(event) => openFolderContextMenu(event, row)}
                  aria-expanded={isBranchFolderOpen(row.id)}
                  title={`${row.name} (${row.branchCount})`}
                >
                  {#if isBranchFolderOpen(row.id)}
                    <ChevronDown size={14} aria-hidden="true" />
                    <FolderOpen size={15} aria-hidden="true" />
                  {:else}
                    <ChevronRight size={14} aria-hidden="true" />
                    <Folder size={15} aria-hidden="true" />
                  {/if}
                  <span class="branch-folder-name">{row.name}</span>
                  <span class="branch-folder-count">{row.branchCount}</span>
                </button>
              {:else}
                <article
                  class="branch-row"
                  class:current={row.branch.current}
                  style={`--branch-indent: ${row.depth * 16}px;`}
                  ondblclick={(event) => checkoutOnDoubleClick(event, row.branch)}
                  oncontextmenu={(event) => openBranchContextMenu(event, row.branch)}
                  title={row.branch.current ? "Current branch" : row.branch.name}
                >
                  <div class="branch-info">
                    <GitBranch size={16} aria-hidden="true" />
                    <div>
                      <strong>{row.displayName}</strong>
                      <span>{row.scopeLabel}</span>
                    </div>
                  </div>
                  {#if row.branch.current}
                    <span class="pill pill-active">Current</span>
                  {/if}
                </article>
              {/if}
            {/each}
          {/if}
        {/if}
      </div>

      <div class="branch-group">
        <div class="tag-group-head">
          <button
            class="branch-group-toggle"
            type="button"
            onclick={() => { tagsOpen = !tagsOpen; }}
            aria-expanded={tagsOpen}
          >
            {#if tagsOpen}
              <ChevronDown size={14} aria-hidden="true" />
            {:else}
              <ChevronRight size={14} aria-hidden="true" />
            {/if}
            <span>Tags</span>
            <span class="branch-group-count">{tags.length}</span>
          </button>
          <button
            class="branch-create-toggle"
            type="button"
            onclick={openTagCreateForm}
            disabled={!hasRepository || isBusy}
            title="Create new tag"
            aria-label="Create new tag"
          >
            <Plus size={13} aria-hidden="true" />
          </button>
        </div>

        {#if tagCreateOpen}
          <form class="branch-create-form tag-create-form" onsubmit={submitCreateTag}>
            <TagIcon size={15} aria-hidden="true" />
            <input
              bind:this={tagCreateInput}
              bind:value={newTagName}
              disabled={isBusy}
              autocomplete="off"
              spellcheck="false"
              placeholder="v1.0.0"
              aria-label="New tag name"
            />
            <input
              bind:value={newTagMessage}
              disabled={isBusy}
              autocomplete="off"
              spellcheck="false"
              placeholder="Message (optional)"
              aria-label="Tag message"
            />
            <button class="branch-create-action confirm" type="submit" disabled={isBusy || newTagName.trim().length === 0} title="Create tag">
              <Check size={14} aria-hidden="true" />
            </button>
            <button class="branch-create-action" type="button" onclick={closeTagCreateForm} disabled={isBusy} title="Cancel">
              <X size={14} aria-hidden="true" />
            </button>
          </form>
        {/if}

        {#if tagsOpen}
          {#if tags.length === 0}
            <div class="branch-empty">No tags.</div>
          {:else}
            {#each tags as tag (tag.name)}
              <article
                class="branch-row"
                oncontextmenu={(event) => openTagContextMenu(event, tag)}
                title={tag.message ?? tag.name}
              >
                <div class="branch-info">
                  <TagIcon size={16} aria-hidden="true" />
                  <div>
                    <strong>{tag.name}</strong>
                    <span>{tag.short_hash}</span>
                  </div>
                </div>
              </article>
            {/each}
          {/if}
        {/if}
      </div>

      <div class="branch-group">
        <button
          class="branch-group-toggle worktree-group-toggle"
          type="button"
          onclick={onManageWorktrees}
          disabled={isBusy}
          aria-haspopup="dialog"
          title="Manage repository worktrees"
        >
          <HardDrive size={14} aria-hidden="true" />
          <span>Worktrees</span>
          <span class="branch-group-count">Manage</span>
        </button>
      </div>
    </div>
  {/if}

  {#if contextBranch}
    <div
      bind:this={branchContextMenuElement}
      class="branch-context-menu"
      style={`left: ${contextMenuX}px; top: ${contextMenuY}px;`}
      role="menu"
      tabindex="-1"
      aria-label={`Actions for ${contextBranch.name}`}
    >
      <button type="button" role="menuitem" onclick={checkoutContextBranch} disabled={isBusy || contextBranch.current}>
        <GitBranch size={14} aria-hidden="true" />
        Checkout
      </button>
      <button type="button" role="menuitem" onclick={compareContextBranch} disabled={isBusy}>
        <GitCompare size={14} aria-hidden="true" />
        Compare with...
      </button>
      <button type="button" role="menuitem" onclick={mergeContextBranch} disabled={isBusy || contextBranch.current}>
        <GitMerge size={14} aria-hidden="true" />
        Merge into current
      </button>
      <button type="button" role="menuitem" onclick={rebaseContextBranch} disabled={isBusy || contextBranch.current}>
        <GitBranch size={14} aria-hidden="true" />
        Rebase current onto this
      </button>
      <button type="button" role="menuitem" onclick={createContextWorktree} disabled={isBusy || contextBranch.remote || contextBranch.current}>
        <HardDrive size={14} aria-hidden="true" />
        Open in new worktree
      </button>
      <div class="menu-separator" role="separator"></div>
      <button type="button" role="menuitem" onclick={renameContextBranch} disabled={isBusy}>
        <Pencil size={14} aria-hidden="true" />
        {contextBranch.remote ? "Rename remote..." : "Rename"}
      </button>
      <button
        class="danger"
        type="button"
        role="menuitem"
        onclick={deleteContextBranch}
        disabled={isBusy || contextBranch.current}
        title={contextBranch.current ? "Current branch cannot be deleted" : contextBranch.remote ? "Delete remote branch" : "Delete local branch"}
      >
        <Trash2 size={14} aria-hidden="true" />
        {contextBranch.remote ? "Delete remote" : "Delete"}
      </button>
    </div>
  {/if}

  {#if contextFolder}
    <div
      bind:this={branchContextMenuElement}
      class="branch-context-menu"
      style={`left: ${contextMenuX}px; top: ${contextMenuY}px;`}
      role="menu"
      tabindex="-1"
      aria-label={`Actions for branch folder ${contextFolder.name}`}
    >
      <button
        class="danger"
        type="button"
        role="menuitem"
        onclick={deleteContextFolder}
        disabled={isBusy || contextFolder.branches.every((branch) => branch.current)}
        title={contextFolder.current ? "The current branch will be kept" : "Delete all branches in this folder"}
      >
        <Trash2 size={14} aria-hidden="true" />
        Delete {contextFolder.branches.filter((branch) => !branch.current).length} branches
      </button>
    </div>
  {/if}

  {#if contextTag}
    <div
      bind:this={tagContextMenuElement}
      class="branch-context-menu"
      style={`left: ${tagContextMenuX}px; top: ${tagContextMenuY}px;`}
      role="menu"
      tabindex="-1"
      aria-label={`Actions for ${contextTag.name}`}
    >
      <button type="button" role="menuitem" onclick={pushContextTag} disabled={isBusy}>
        <Upload size={14} aria-hidden="true" />
        Push to remote
      </button>
      <div class="menu-separator" role="separator"></div>
      <button class="danger" type="button" role="menuitem" onclick={deleteContextTag} disabled={isBusy} title="Delete local tag">
        <Trash2 size={14} aria-hidden="true" />
        Delete
      </button>
    </div>
  {/if}
</section>
