"use client"

import { useState, useMemo } from "react"
import Link from "next/link"
import { usePathname, useSearchParams } from "next/navigation"
import {
  DndContext,
  DragOverlay,
  PointerSensor,
  useSensor,
  useSensors,
  closestCenter,
  type DragStartEvent,
  type DragEndEvent,
} from "@dnd-kit/core"
import {
  SortableContext,
  useSortable,
  verticalListSortingStrategy,
} from "@dnd-kit/sortable"
import { CSS } from "@dnd-kit/utilities"
import { useSubscriptions } from "@/lib/queries/use-subscriptions"
import { useUnreadCounts } from "@/lib/queries/use-unread-counts"
import { useCustomFeeds } from "@/lib/queries/use-custom-feeds"
import { useMoveSubscriptionToFolder } from "@/lib/queries/use-subscription-mutations"
import {
  useReorderSubscriptions,
  useReorderFolders,
  useReorderCustomFeeds,
} from "@/lib/queries/use-reorder-mutations"
import { computeReorderPositions } from "@/lib/reorder-positions"
import { useUserInterfaceStore } from "@/lib/stores/user-interface-store"
import { classNames } from "@/lib/utilities"
import type { Subscription, Folder } from "@/lib/types/subscription"
import type { CustomFeed } from "@/lib/types/custom-feed"

const NAVIGATION_LINK_CLASS =
  "block whitespace-nowrap px-2 py-1 text-text-secondary transition-colors hover:bg-background-tertiary hover:text-text-primary"

const ACTIVE_LINK_CLASS = "bg-background-tertiary text-text-primary"

function getFaviconUrl(feedUrl: string): string | null {
  try {
    const hostname = new URL(feedUrl).hostname
    return `https://www.google.com/s2/favicons?domain=${hostname}&sz=16`
  } catch {
    return null
  }
}

function FeedFavicon({ feedUrl }: { feedUrl: string }) {
  const faviconUrl = getFaviconUrl(feedUrl)
  if (!faviconUrl) return null

  return (
    <img
      src={faviconUrl}
      alt=""
      width={16}
      height={16}
      className="shrink-0"
      loading="lazy"
    />
  )
}

function displayNameForSubscription(subscription: {
  customTitle: string | null
  feedTitle: string
  feedUrl: string
}): string {
  if (subscription.customTitle) return subscription.customTitle
  if (subscription.feedTitle) return subscription.feedTitle

  try {
    return new URL(subscription.feedUrl).hostname
  } catch {
    return subscription.feedUrl || "untitled feed"
  }
}

function UnreadBadge({ count }: { count: number }) {
  if (count === 0) return null

  return (
    <span className="ml-auto shrink-0 text-[0.625rem] tabular-nums text-text-dim">
      {count > 999 ? "999+" : count}
    </span>
  )
}

function sidebarFocusClass(
  focusedPanel: string,
  focusedSidebarIndex: number,
  navigationIndex: number
): string {
  return focusedPanel === "sidebar" && focusedSidebarIndex === navigationIndex
    ? "bg-background-tertiary text-text-primary"
    : ""
}

function SortableFeedItem({
  subscription,
  activeFeedIdentifier,
  showFeedFavicons,
  unreadCount,
  focusedPanel,
  focusedSidebarIndex,
  navigationIndex,
  indentClass,
  closeSidebarOnMobile,
}: {
  subscription: Subscription
  activeFeedIdentifier: string | null
  showFeedFavicons: boolean
  unreadCount: number
  focusedPanel: string
  focusedSidebarIndex: number
  navigationIndex: number
  indentClass: string
  closeSidebarOnMobile: () => void
}) {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id: subscription.subscriptionIdentifier })

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.4 : undefined,
  }

  return (
    <Link
      ref={setNodeRef}
      style={style}
      {...attributes}
      {...listeners}
      href={`/reader?feed=${subscription.feedIdentifier}`}
      data-sidebar-nav-item
      {...(unreadCount > 0 ? { "data-has-unreads": "" } : {})}
      onClick={closeSidebarOnMobile}
      className={classNames(
        NAVIGATION_LINK_CLASS,
        `flex items-center truncate ${indentClass} text-[0.85em]`,
        activeFeedIdentifier === subscription.feedIdentifier && ACTIVE_LINK_CLASS,
        subscription.hiddenFromTimeline && "opacity-50",
        sidebarFocusClass(focusedPanel, focusedSidebarIndex, navigationIndex)
      )}
    >
      {showFeedFavicons && <FeedFavicon feedUrl={subscription.feedUrl} />}
      <span
        className={classNames("truncate", showFeedFavicons && "ml-2")}
      >
        {displayNameForSubscription(subscription)}
      </span>
      {subscription.feedVisibility === "authenticated" && (
        <span
          className="ml-1 shrink-0 text-text-dim"
          title="authenticated feed"
        >
          &#128274;
        </span>
      )}
      {subscription.feedType === "podcast" && (
        <span className="ml-1 shrink-0 text-text-dim" title="podcast">
          &#9835;
        </span>
      )}
      {subscription.consecutiveFailures > 0 && (
        <span
          className="ml-1 shrink-0 text-status-warning"
          title={subscription.lastFetchError ?? "feed error"}
        >
          [!]
        </span>
      )}
      <UnreadBadge count={unreadCount} />
    </Link>
  )
}

function SortableFolderItem({
  folder,
  isExpanded,
  folderSubscriptions,
  folderUnreadCount,
  activeFeedIdentifier,
  activeFolderIdentifier,
  showFeedFavicons,
  unreadCounts,
  focusedPanel,
  focusedSidebarIndex,
  folderNavigationIndex,
  feedNavigationIndexStart,
  toggleFolderExpansion,
  closeSidebarOnMobile,
}: {
  folder: Folder
  isExpanded: boolean
  folderSubscriptions: Subscription[]
  folderUnreadCount: number
  activeFeedIdentifier: string | null
  activeFolderIdentifier: string | null
  showFeedFavicons: boolean
  unreadCounts: Record<string, number> | undefined
  focusedPanel: string
  focusedSidebarIndex: number
  folderNavigationIndex: number
  feedNavigationIndexStart: number
  toggleFolderExpansion: (identifier: string) => void
  closeSidebarOnMobile: () => void
}) {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id: folder.folderIdentifier })

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.4 : undefined,
  }

  const feedIdentifiers = useMemo(
    () => folderSubscriptions.map((subscription) => subscription.subscriptionIdentifier),
    [folderSubscriptions]
  )

  return (
    <div
      ref={setNodeRef}
      style={style}
      className="mt-2"
    >
      <div
        data-sidebar-nav-item
        {...(folderUnreadCount > 0 ? { "data-has-unreads": "" } : {})}
        {...attributes}
        {...listeners}
        className={classNames(
          "flex w-full items-center gap-1 px-2 py-1",
          sidebarFocusClass(
            focusedPanel,
            focusedSidebarIndex,
            folderNavigationIndex
          )
        )}
      >
        <button
          type="button"
          aria-expanded={isExpanded}
          onClick={(event) => {
            event.stopPropagation()
            toggleFolderExpansion(folder.folderIdentifier)
          }}
          className="shrink-0 px-0.5 text-text-secondary transition-colors hover:text-text-primary"
        >
          {isExpanded ? "\u25BE" : "\u25B8"}
        </button>
        <Link
          href={`/reader?folder=${folder.folderIdentifier}`}
          onClick={closeSidebarOnMobile}
          className={classNames(
            "flex flex-1 items-center gap-2 truncate text-text-secondary transition-colors hover:text-text-primary",
            activeFolderIdentifier === folder.folderIdentifier &&
              "text-text-primary"
          )}
        >
          {folder.iconUrl && (
            <img
              src={folder.iconUrl}
              alt=""
              width={16}
              height={16}
              className="shrink-0"
              loading="lazy"
            />
          )}
          <span className="truncate">{folder.name}</span>
        </Link>
        <UnreadBadge count={folderUnreadCount} />
      </div>
      {isExpanded && (
        <SortableContext
          items={feedIdentifiers}
          strategy={verticalListSortingStrategy}
        >
          <div className="space-y-0.5">
            {folderSubscriptions.map((subscription, subscriptionIndex) => (
              <SortableFeedItem
                key={subscription.subscriptionIdentifier}
                subscription={subscription}
                activeFeedIdentifier={activeFeedIdentifier}
                showFeedFavicons={showFeedFavicons}
                unreadCount={
                  unreadCounts?.[subscription.feedIdentifier] ?? 0
                }
                focusedPanel={focusedPanel}
                focusedSidebarIndex={focusedSidebarIndex}
                navigationIndex={feedNavigationIndexStart + subscriptionIndex}
                indentClass="pl-6"
                closeSidebarOnMobile={closeSidebarOnMobile}
              />
            ))}
          </div>
        </SortableContext>
      )}
    </div>
  )
}

function SortableCustomFeedItem({
  customFeed,
  activeCustomFeedIdentifier,
  focusedPanel,
  focusedSidebarIndex,
  navigationIndex,
  closeSidebarOnMobile,
}: {
  customFeed: CustomFeed
  activeCustomFeedIdentifier: string | null
  focusedPanel: string
  focusedSidebarIndex: number
  navigationIndex: number
  closeSidebarOnMobile: () => void
}) {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id: customFeed.identifier })

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.4 : undefined,
  }

  return (
    <Link
      ref={setNodeRef}
      style={style}
      {...attributes}
      {...listeners}
      href={`/reader?custom_feed=${customFeed.identifier}`}
      data-sidebar-nav-item
      onClick={closeSidebarOnMobile}
      className={classNames(
        NAVIGATION_LINK_CLASS,
        "flex items-center gap-2 truncate pl-4 text-[0.85em]",
        activeCustomFeedIdentifier === customFeed.identifier &&
          ACTIVE_LINK_CLASS,
        sidebarFocusClass(focusedPanel, focusedSidebarIndex, navigationIndex)
      )}
    >
      {customFeed.iconUrl && (
        <img
          src={customFeed.iconUrl}
          alt=""
          width={16}
          height={16}
          className="shrink-0"
          loading="lazy"
        />
      )}
      <span className="truncate">{customFeed.name}</span>
    </Link>
  )
}

function FeedDragOverlay({
  subscription,
  showFeedFavicons,
}: {
  subscription: Subscription
  showFeedFavicons: boolean
}) {
  return (
    <div
      className={classNames(
        NAVIGATION_LINK_CLASS,
        "flex items-center truncate text-[0.85em] bg-background-secondary shadow-lg outline outline-1 outline-border"
      )}
    >
      {showFeedFavicons && <FeedFavicon feedUrl={subscription.feedUrl} />}
      <span className={classNames("truncate", showFeedFavicons && "ml-2")}>
        {displayNameForSubscription(subscription)}
      </span>
    </div>
  )
}

function FolderDragOverlay({ folder }: { folder: Folder }) {
  return (
    <div className="flex items-center gap-1 px-2 py-1 bg-background-secondary shadow-lg outline outline-1 outline-border">
      <span className="shrink-0 px-0.5 text-text-secondary">{"\u25B8"}</span>
      <span className="truncate text-text-secondary">{folder.name}</span>
    </div>
  )
}

function CustomFeedDragOverlay({ customFeed }: { customFeed: CustomFeed }) {
  return (
    <div
      className={classNames(
        NAVIGATION_LINK_CLASS,
        "flex items-center gap-2 truncate text-[0.85em] bg-background-secondary shadow-lg outline outline-1 outline-border"
      )}
    >
      {customFeed.iconUrl && (
        <img
          src={customFeed.iconUrl}
          alt=""
          width={16}
          height={16}
          className="shrink-0"
          loading="lazy"
        />
      )}
      <span className="truncate">{customFeed.name}</span>
    </div>
  )
}

type DragItemType = "feed" | "folder" | "customFeed"

export function SidebarContent() {
  const pathname = usePathname()
  const searchParameters = useSearchParams()
  const { data } = useSubscriptions()
  const { data: unreadCounts } = useUnreadCounts()
  const { data: customFeedsData } = useCustomFeeds()
  const setAddFeedDialogOpen = useUserInterfaceStore(
    (state) => state.setAddFeedDialogOpen
  )
  const toggleSidebar = useUserInterfaceStore((state) => state.toggleSidebar)
  const showFeedFavicons = useUserInterfaceStore(
    (state) => state.showFeedFavicons
  )
  const expandedFolderIdentifiers = useUserInterfaceStore(
    (state) => state.expandedFolderIdentifiers
  )
  const toggleFolderExpansion = useUserInterfaceStore(
    (state) => state.toggleFolderExpansion
  )
  const focusedPanel = useUserInterfaceStore((state) => state.focusedPanel)
  const focusedSidebarIndex = useUserInterfaceStore(
    (state) => state.focusedSidebarIndex
  )
  const showFoldersAboveFeeds = useUserInterfaceStore(
    (state) => state.showFoldersAboveFeeds
  )

  const moveToFolder = useMoveSubscriptionToFolder()
  const reorderSubscriptions = useReorderSubscriptions()
  const reorderFolders = useReorderFolders()
  const reorderCustomFeeds = useReorderCustomFeeds()

  const [activeDragIdentifier, setActiveDragIdentifier] = useState<string | null>(null)
  const [activeDragType, setActiveDragType] = useState<DragItemType | null>(
    null
  )

  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: { distance: 5 },
    })
  )

  function closeSidebarOnMobile() {
    if (typeof window !== "undefined" && window.innerWidth < 768) {
      toggleSidebar()
    }
  }

  const folders = data?.folders ?? []
  const subscriptions = data?.subscriptions ?? []
  const customFeeds = customFeedsData ?? []
  const ungroupedSubscriptions = subscriptions.filter(
    (subscription) => !subscription.folderIdentifier
  )

  const totalUnreadCount = subscriptions
    .filter((subscription) => !subscription.hiddenFromTimeline)
    .reduce(
      (sum, subscription) =>
        sum + (unreadCounts?.[subscription.feedIdentifier] ?? 0),
      0
    )

  function getFolderUnreadCount(folderIdentifier: string): number {
    return subscriptions
      .filter(
        (subscription) =>
          subscription.folderIdentifier === folderIdentifier &&
          !subscription.hiddenFromTimeline
      )
      .reduce(
        (sum, subscription) =>
          sum + (unreadCounts?.[subscription.feedIdentifier] ?? 0),
        0
      )
  }

  const activeFeedIdentifier = searchParameters.get("feed")
  const activeFolderIdentifier = searchParameters.get("folder")
  const activeCustomFeedIdentifier = searchParameters.get("custom_feed")

  const subscriptionMap = useMemo(
    () =>
      new Map(subscriptions.map((subscription) => [subscription.subscriptionIdentifier, subscription])),
    [subscriptions]
  )
  const folderMap = useMemo(
    () => new Map(folders.map((folder) => [folder.folderIdentifier, folder])),
    [folders]
  )
  const customFeedMap = useMemo(
    () => new Map(customFeeds.map((customFeed) => [customFeed.identifier, customFeed])),
    [customFeeds]
  )

  const folderIdentifiers = useMemo(
    () => folders.map((folder) => folder.folderIdentifier),
    [folders]
  )
  const ungroupedFeedIdentifiers = useMemo(
    () => ungroupedSubscriptions.map((subscription) => subscription.subscriptionIdentifier),
    [ungroupedSubscriptions]
  )
  const customFeedIdentifiers = useMemo(
    () => customFeeds.map((customFeed) => customFeed.identifier),
    [customFeeds]
  )

  function identifyDragType(identifier: string): DragItemType | null {
    if (subscriptionMap.has(identifier)) return "feed"
    if (folderMap.has(identifier)) return "folder"
    if (customFeedMap.has(identifier)) return "customFeed"

    return null
  }

  function handleDragStart(event: DragStartEvent) {
    const identifier = String(event.active.id)
    setActiveDragIdentifier(identifier)
    setActiveDragType(identifyDragType(identifier))
  }

  function handleDragEnd(event: DragEndEvent) {
    setActiveDragIdentifier(null)
    setActiveDragType(null)

    const { active, over } = event
    if (!over || active.id === over.id) return

    const activeIdentifier = String(active.id)
    const overIdentifier = String(over.id)
    const dragType = identifyDragType(activeIdentifier)

    if (dragType === "folder") {
      const items = folders.map((folder) => ({
        identifier: folder.folderIdentifier,
        position: folder.position,
      }))
      const result = computeReorderPositions(items, activeIdentifier, overIdentifier)
      if (result) reorderFolders.mutate(result)

      return
    }

    if (dragType === "customFeed") {
      const items = customFeeds.map((customFeed) => ({
        identifier: customFeed.identifier,
        position: customFeed.position,
      }))
      const result = computeReorderPositions(items, activeIdentifier, overIdentifier)
      if (result) reorderCustomFeeds.mutate(result)

      return
    }

    if (dragType === "feed") {
      const activeSubscription = subscriptionMap.get(activeIdentifier)
      const overSubscription = subscriptionMap.get(overIdentifier)

      if (!activeSubscription) return

      if (overSubscription) {
        if (activeSubscription.folderIdentifier === overSubscription.folderIdentifier) {
          const containerSubscriptions = subscriptions
            .filter(
              (subscription) => subscription.folderIdentifier === activeSubscription.folderIdentifier
            )
            .map((subscription) => ({
              identifier: subscription.subscriptionIdentifier,
              position: subscription.position,
            }))

          const result = computeReorderPositions(
            containerSubscriptions,
            activeIdentifier,
            overIdentifier
          )
          if (result) reorderSubscriptions.mutate(result)
        } else {
          const targetFolderIdentifier = overSubscription.folderIdentifier
          const targetFolderName = targetFolderIdentifier
            ? folderMap.get(targetFolderIdentifier)?.name
            : undefined

          moveToFolder.mutate({
            subscriptionIdentifier: activeIdentifier,
            folderIdentifier: targetFolderIdentifier,
            feedTitle:
              activeSubscription.customTitle ?? activeSubscription.feedTitle ?? undefined,
            folderName: targetFolderName,
          })
        }
      }
    }
  }

  function handleDragCancel() {
    setActiveDragIdentifier(null)
    setActiveDragType(null)
  }

  function renderDragOverlay() {
    if (!activeDragIdentifier || !activeDragType) return null

    if (activeDragType === "feed") {
      const subscription = subscriptionMap.get(activeDragIdentifier)
      if (!subscription) return null

      return (
        <FeedDragOverlay
          subscription={subscription}
          showFeedFavicons={showFeedFavicons}
        />
      )
    }

    if (activeDragType === "folder") {
      const folder = folderMap.get(activeDragIdentifier)
      if (!folder) return null

      return <FolderDragOverlay folder={folder} />
    }

    if (activeDragType === "customFeed") {
      const customFeed = customFeedMap.get(activeDragIdentifier)
      if (!customFeed) return null

      return <CustomFeedDragOverlay customFeed={customFeed} />
    }

    return null
  }

  const folderData = folders.map((folder) => {
    const isExpanded = expandedFolderIdentifiers.includes(
      folder.folderIdentifier
    )
    const folderSubscriptions = subscriptions.filter(
      (subscription) =>
        subscription.folderIdentifier === folder.folderIdentifier
    )
    const folderUnreadCount = getFolderUnreadCount(folder.folderIdentifier)

    return {
      folder,
      isExpanded,
      folderSubscriptions,
      folderUnreadCount,
    }
  })

  let navigationIndex = 0

  const staticNavigationStart = navigationIndex
  navigationIndex += 4

  const customFeedNavigationStart = navigationIndex
  navigationIndex += customFeeds.length

  const sections = showFoldersAboveFeeds
    ? (["folders", "ungrouped"] as const)
    : (["ungrouped", "folders"] as const)

  const folderNavigationIndices: { folderNavigationIndex: number; feedNavigationIndexStart: number }[] = []
  let ungroupedNavigationStart = 0

  for (const section of sections) {
    if (section === "folders") {
      for (const folderDatum of folderData) {
        folderNavigationIndices.push({
          folderNavigationIndex: navigationIndex++,
          feedNavigationIndexStart: navigationIndex,
        })
        if (folderDatum.isExpanded) navigationIndex += folderDatum.folderSubscriptions.length
      }
    } else {
      ungroupedNavigationStart = navigationIndex
      navigationIndex += ungroupedSubscriptions.length
    }
  }

  const addFeedNavigationIndex = navigationIndex

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragStart={handleDragStart}
      onDragEnd={handleDragEnd}
      onDragCancel={handleDragCancel}
    >
      <nav data-sidebar-nav className="flex-1 space-y-1 overflow-auto px-2">
        <Link
          href="/reader"
          data-sidebar-nav-item
          {...(totalUnreadCount > 0 ? { "data-has-unreads": "" } : {})}
          onClick={closeSidebarOnMobile}
          className={classNames(
            NAVIGATION_LINK_CLASS,
            "flex items-center",
            pathname === "/reader" &&
              !activeFeedIdentifier &&
              !activeFolderIdentifier &&
              !activeCustomFeedIdentifier &&
              ACTIVE_LINK_CLASS,
            sidebarFocusClass(focusedPanel, focusedSidebarIndex, staticNavigationStart)
          )}
        >
          <span>all entries</span>
          <UnreadBadge count={totalUnreadCount} />
        </Link>
        <Link
          href="/reader/saved"
          data-sidebar-nav-item
          onClick={closeSidebarOnMobile}
          className={classNames(
            NAVIGATION_LINK_CLASS,
            pathname === "/reader/saved" && ACTIVE_LINK_CLASS,
            sidebarFocusClass(focusedPanel, focusedSidebarIndex, staticNavigationStart + 1)
          )}
        >
          saved
        </Link>
        <Link
          href="/reader/highlights"
          data-sidebar-nav-item
          onClick={closeSidebarOnMobile}
          className={classNames(
            NAVIGATION_LINK_CLASS,
            pathname === "/reader/highlights" && ACTIVE_LINK_CLASS,
            sidebarFocusClass(focusedPanel, focusedSidebarIndex, staticNavigationStart + 2)
          )}
        >
          highlights
        </Link>
        <Link
          href="/reader/shares"
          data-sidebar-nav-item
          onClick={closeSidebarOnMobile}
          className={classNames(
            NAVIGATION_LINK_CLASS,
            pathname === "/reader/shares" && ACTIVE_LINK_CLASS,
            sidebarFocusClass(focusedPanel, focusedSidebarIndex, staticNavigationStart + 3)
          )}
        >
          shares
        </Link>

        {customFeeds.length > 0 && (
          <SortableContext
            items={customFeedIdentifiers}
            strategy={verticalListSortingStrategy}
          >
            <div className="mt-3 space-y-0.5">
              {customFeeds.map((customFeed, customFeedIndex) => (
                <SortableCustomFeedItem
                  key={customFeed.identifier}
                  customFeed={customFeed}
                  activeCustomFeedIdentifier={activeCustomFeedIdentifier}
                  focusedPanel={focusedPanel}
                  focusedSidebarIndex={focusedSidebarIndex}
                  navigationIndex={customFeedNavigationStart + customFeedIndex}
                  closeSidebarOnMobile={closeSidebarOnMobile}
                />
              ))}
            </div>
          </SortableContext>
        )}

        {sections.map((section) =>
          section === "folders" ? (
            <SortableContext
              key="folders"
              items={folderIdentifiers}
              strategy={verticalListSortingStrategy}
            >
              {folderData.map((folderDatum, folderIndex) => (
                <SortableFolderItem
                  key={folderDatum.folder.folderIdentifier}
                  folder={folderDatum.folder}
                  isExpanded={folderDatum.isExpanded}
                  folderSubscriptions={folderDatum.folderSubscriptions}
                  folderUnreadCount={folderDatum.folderUnreadCount}
                  activeFeedIdentifier={activeFeedIdentifier}
                  activeFolderIdentifier={activeFolderIdentifier}
                  showFeedFavicons={showFeedFavicons}
                  unreadCounts={unreadCounts}
                  focusedPanel={focusedPanel}
                  focusedSidebarIndex={focusedSidebarIndex}
                  folderNavigationIndex={folderNavigationIndices[folderIndex].folderNavigationIndex}
                  feedNavigationIndexStart={folderNavigationIndices[folderIndex].feedNavigationIndexStart}
                  toggleFolderExpansion={toggleFolderExpansion}
                  closeSidebarOnMobile={closeSidebarOnMobile}
                />
              ))}
            </SortableContext>
          ) : (
            <SortableContext
              key="ungrouped"
              items={ungroupedFeedIdentifiers}
              strategy={verticalListSortingStrategy}
            >
              <div className="mt-3 space-y-0.5">
                {ungroupedSubscriptions.map((subscription, subscriptionIndex) => (
                  <SortableFeedItem
                    key={subscription.subscriptionIdentifier}
                    subscription={subscription}
                    activeFeedIdentifier={activeFeedIdentifier}
                    showFeedFavicons={showFeedFavicons}
                    unreadCount={
                      unreadCounts?.[subscription.feedIdentifier] ?? 0
                    }
                    focusedPanel={focusedPanel}
                    focusedSidebarIndex={focusedSidebarIndex}
                    navigationIndex={ungroupedNavigationStart + subscriptionIndex}
                    indentClass="pl-4"
                    closeSidebarOnMobile={closeSidebarOnMobile}
                  />
                ))}
              </div>
            </SortableContext>
          )
        )}

        <div className="mt-3 space-y-0.5">
          <button
            type="button"
            data-sidebar-nav-item
            onClick={() => setAddFeedDialogOpen(true)}
            className={classNames(
              "w-full px-2 py-1 text-left text-text-dim transition-colors hover:bg-background-tertiary hover:text-text-secondary",
              sidebarFocusClass(
                focusedPanel,
                focusedSidebarIndex,
                addFeedNavigationIndex
              )
            )}
          >
            + add feed
          </button>
        </div>
      </nav>

      <DragOverlay dropAnimation={null}>{renderDragOverlay()}</DragOverlay>
    </DndContext>
  )
}
