<script lang="ts">
  import {type TrustedEvent} from "@welshman/util"
  import Button from "@lib/components/Button.svelte"
  import Icon from "@lib/components/Icon.svelte"
  import Link from "@lib/components/Link.svelte"
  import SecondaryNav from "@lib/components/SecondaryNav.svelte"
  import SecondaryNavHeader from "@lib/components/SecondaryNavHeader.svelte"
  import SecondaryNavSection from "@lib/components/SecondaryNavSection.svelte"
  import Bookmark from "@assets/icons/bookmark.svg?dataurl"
  import Folder from "@assets/icons/folder.svg?dataurl"
  import Add from "@assets/icons/add.svg?dataurl"

  type BookmarkList = {
    key: string
    label: string
    count: number
    event?: TrustedEvent
  }

  type Props = {
    lists: BookmarkList[]
    selectedKey: string
    totalCount: number
    onOpenManager: () => void
    onSelect: (key: string) => void
    onRename: (key: string, label: string, nextLabel: string) => Promise<void>
    onDelete: (key: string, label: string) => Promise<void>
  }

  const {lists, selectedKey, totalCount, onOpenManager, onSelect, onRename, onDelete}: Props =
    $props()

  let menuOpen = $state(false)
  let menuX = $state(0)
  let menuY = $state(0)
  let menuListKey = $state("")
  let menuListLabel = $state("")
  let listDialogMode: "rename" | "delete" | undefined = $state()
  let dialogListKey = $state("")
  let dialogListLabel = $state("")
  let nextListLabel = $state("")
  let dialogPending = $state(false)

  const closeMenu = () => {
    menuOpen = false
  }

  const openListMenu = (event: MouseEvent, key: string, label: string) => {
    event.preventDefault()
    menuOpen = true
    menuX = event.clientX
    menuY = event.clientY
    menuListKey = key
    menuListLabel = label
  }

  const openMenuList = () => {
    closeMenu()
    onSelect(menuListKey)
  }

  const openRenameDialog = () => {
    closeMenu()
    listDialogMode = "rename"
    dialogListKey = menuListKey
    dialogListLabel = menuListLabel
    nextListLabel = menuListLabel
  }

  const openDeleteDialog = () => {
    closeMenu()
    listDialogMode = "delete"
    dialogListKey = menuListKey
    dialogListLabel = menuListLabel
    nextListLabel = menuListLabel
  }

  const closeDialog = (force = false) => {
    if (!force && dialogPending) {
      return
    }

    listDialogMode = undefined
    dialogListKey = ""
    dialogListLabel = ""
    nextListLabel = ""
  }

  const submitRename = async () => {
    if (listDialogMode !== "rename") {
      return
    }

    dialogPending = true

    try {
      await onRename(dialogListKey, dialogListLabel, nextListLabel)
      closeDialog(true)
    } finally {
      dialogPending = false
    }
  }

  const submitDelete = async () => {
    if (listDialogMode !== "delete") {
      return
    }

    dialogPending = true

    try {
      await onDelete(dialogListKey, dialogListLabel)
      closeDialog(true)
    } finally {
      dialogPending = false
    }
  }

  const handleWindowKeydown = (event: KeyboardEvent) => {
    if (event.key === "Escape") {
      closeMenu()
      closeDialog()
    }
  }
</script>

<svelte:window onclick={closeMenu} onkeydown={handleWindowKeydown} />

<SecondaryNav class="relative">
  <SecondaryNavSection>
    <SecondaryNavHeader>
      <span class="flex items-center gap-2 uppercase tracking-wide">
        <Icon icon={Bookmark} />
        Bookmarks
      </span>
      <span class="badge badge-sm badge-neutral">{totalCount}</span>
    </SecondaryNavHeader>
    <div
      class="flex items-center justify-between px-1 pt-1 text-xs uppercase tracking-wide opacity-70">
      <span>My Lists</span>
      <Button class="btn btn-ghost btn-xs btn-square" onclick={onOpenManager}>
        <Icon size={3.5} icon={Add} />
      </Button>
    </div>
  </SecondaryNavSection>

  <div class="col-2 gap-2 overflow-y-auto px-2 pb-2">
    {#each lists as list (list.key)}
      <div
        role="button"
        tabindex="-1"
        oncontextmenu={event => openListMenu(event, list.key, list.label)}>
        <Link href={`/bookmarks?list=${encodeURIComponent(list.key)}`}>
          <div
            class={`card2 card2-sm bg-alt col-2 gap-1 transition-colors hover:bg-base-100 ${selectedKey === list.key ? "bg-base-100" : ""}`}>
            <div class="flex items-center justify-between gap-2">
              <p class="truncate font-medium">
                <span class="inline-flex items-center gap-2">
                  <Icon size={4} icon={list.key.startsWith("10003:") ? Bookmark : Folder} />
                  {list.label}
                </span>
              </p>
              <span class="badge badge-sm badge-neutral">{list.count}</span>
            </div>
          </div>
        </Link>
      </div>
    {:else}
      <div class="card2 card2-sm bg-alt text-sm opacity-70">No lists found yet.</div>
    {/each}
  </div>

  {#if menuOpen}
    <div class="fixed inset-0 z-popover" role="presentation">
      <div
        class="menu rounded-box bg-base-100 shadow-xl"
        role="menu"
        style={`position: fixed; left: ${menuX}px; top: ${menuY}px; min-width: 11rem;`}>
        <li>
          <Button class="justify-start" onclick={openMenuList}>Open List</Button>
        </li>
        {#if menuListKey !== selectedKey}
          <li>
            <Button class="justify-start" onclick={openRenameDialog}>Rename List</Button>
          </li>
          <li>
            <Button class="justify-start text-error" onclick={openDeleteDialog}>Delete List</Button>
          </li>
        {/if}
      </div>
    </div>
  {/if}

  {#if listDialogMode}
    <div class="fixed inset-0 z-modal bg-black/45 p-4 md:p-6">
      <button
        type="button"
        class="absolute inset-0"
        aria-label="Close dialog"
        onclick={() => closeDialog()}></button>
      <div class="center relative h-full w-full">
        <div
          class="card2 bg-base-100 w-full max-w-md gap-4 p-5 shadow-2xl"
          role="dialog"
          aria-modal="true"
          tabindex="-1">
          {#if listDialogMode === "rename"}
            <div class="col-2 gap-1">
              <h3 class="text-lg font-semibold">Rename List</h3>
              <p class="text-sm opacity-70">Choose a new name for "{dialogListLabel}".</p>
            </div>

            <label class="input input-bordered flex items-center gap-2">
              <Icon icon={Folder} />
              <input bind:value={nextListLabel} class="grow" type="text" placeholder="List name" />
            </label>

            <div class="flex items-center justify-end gap-2">
              <Button class="btn btn-ghost" onclick={() => closeDialog()} disabled={dialogPending}
                >Cancel</Button>
              <Button
                class="btn btn-neutral"
                onclick={submitRename}
                disabled={dialogPending || !nextListLabel.trim()}>
                Save
              </Button>
            </div>
          {:else}
            <div class="col-2 gap-1">
              <h3 class="text-lg font-semibold">Delete List?</h3>
              <p class="text-sm opacity-70">
                This will remove "{dialogListLabel}" and cannot be undone.
              </p>
            </div>

            <div class="flex items-center justify-end gap-2">
              <Button class="btn btn-ghost" onclick={() => closeDialog()} disabled={dialogPending}
                >Cancel</Button>
              <Button class="btn btn-error" onclick={submitDelete} disabled={dialogPending}
                >Delete</Button>
            </div>
          {/if}
        </div>
      </div>
    </div>
  {/if}
</SecondaryNav>
