"use client"

import { useState, useEffect, useRef } from "react"
import { Group, Panel, Separator, useDefaultLayout, useGroupRef } from "react-resizable-panels"
import { useUserInterfaceStore } from "@/lib/stores/user-interface-store"
import { useMarkAllAsRead } from "@/lib/queries/use-mark-all-as-read"
import { useSubscriptions } from "@/lib/queries/use-subscriptions"
import { useUnreadCounts } from "@/lib/queries/use-unread-counts"
import { useUpdateSubscriptionTitle } from "@/lib/queries/use-subscription-mutations"
import { useRenameFolder } from "@/lib/queries/use-folder-mutations"
import { useUpdateCustomFeed } from "@/lib/queries/use-custom-feed-mutations"
import { useIsMobile } from "@/lib/hooks/use-is-mobile"
import { classNames } from "@/lib/utilities"
import { EntryList } from "./entry-list"
import { EntryDetailPanel } from "./entry-detail-panel"
import { ErrorBoundary } from "./error-boundary"
import { useRealtimeEntries } from "@/lib/hooks/use-realtime-entries"
import { useCustomFeeds } from "@/lib/queries/use-custom-feeds"

interface ReaderShellProperties {
  feedFilter: "all" | "saved"
  folderIdentifier?: string | null
  feedIdentifier?: string | null
  customFeedIdentifier?: string | null
}

export function ReaderShell({
  feedFilter,
  folderIdentifier,
  feedIdentifier,
  customFeedIdentifier,
}: ReaderShellProperties) {
  const selectedEntryIdentifier = useUserInterfaceStore(
    (state) => state.selectedEntryIdentifier
  )
  const setSelectedEntryIdentifier = useUserInterfaceStore(
    (state) => state.setSelectedEntryIdentifier
  )
  const entryListViewMode = useUserInterfaceStore(
    (state) => state.entryListViewMode
  )
  const setEntryListViewMode = useUserInterfaceStore(
    (state) => state.setEntryListViewMode
  )
  const setSearchOpen = useUserInterfaceStore((state) => state.setSearchOpen)
  const markAllAsRead = useMarkAllAsRead()
  const { data: subscriptionsData } = useSubscriptions()
  const { data: unreadCounts } = useUnreadCounts()
  const { data: customFeedsData } = useCustomFeeds()
  const isMobile = useIsMobile()
  const focusedPanel = useUserInterfaceStore((state) => state.focusedPanel)
  const toggleShortcutsDialog = useUserInterfaceStore(
    (state) => state.toggleShortcutsDialog
  )
  const navigableEntryIdentifiers = useUserInterfaceStore(
    (state) => state.navigableEntryIdentifiers
  )
  const toolbarPosition = useUserInterfaceStore(
    (state) => state.toolbarPosition
  )

  const detailLayout = useDefaultLayout({
    id: "asa-detail-layout",
    panelIds: ["entry-list", "detail-panel"],
    storage: typeof window !== "undefined" ? localStorage : { getItem: () => null, setItem: () => {} },
  })

  const detailGroupRef = useGroupRef()
  const detailOnLayoutChangedRef = useRef(detailLayout.onLayoutChanged)

  useEffect(() => {
    detailOnLayoutChangedRef.current = detailLayout.onLayoutChanged
  }, [detailLayout.onLayoutChanged])

  useEffect(() => {
    useUserInterfaceStore.getState().setResetDetailLayout(() => {
      const group = detailGroupRef.current
      if (!group) return
      const currentLayout = group.getLayout()
      const panelIdentifiers = Object.keys(currentLayout)
      if (panelIdentifiers.length === 0) return
      const equalSharePercentage = 100 / panelIdentifiers.length
      const equalLayout: Record<string, number> = {}
      for (const panelIdentifier of panelIdentifiers) {
        equalLayout[panelIdentifier] = equalSharePercentage
      }
      const appliedLayout = group.setLayout(equalLayout)
      detailOnLayoutChangedRef.current?.(appliedLayout)
    })
    return () => useUserInterfaceStore.getState().setResetDetailLayout(null)
  }, [detailGroupRef])

  useEffect(() => {
    useUserInterfaceStore.getState().setCurrentFeedIdentifier(feedIdentifier ?? null)
    useUserInterfaceStore.getState().setCurrentFolderIdentifier(folderIdentifier ?? null)
  }, [feedIdentifier, folderIdentifier])

  useRealtimeEntries()

  const updateSubscriptionTitle = useUpdateSubscriptionTitle()
  const renameFolder = useRenameFolder()
  const updateCustomFeed = useUpdateCustomFeed()
  const [isRenamingTitle, setIsRenamingTitle] = useState(false)
  const [renameValue, setRenameValue] = useState("")

  let pageTitle = feedFilter === "saved" ? "saved" : "all entries"
  let isRenameable = false

  const matchingSubscription =
    feedFilter === "all" && feedIdentifier && subscriptionsData
      ? subscriptionsData.subscriptions.find(
          (subscription) => subscription.feedIdentifier === feedIdentifier
        )
      : undefined

  const matchingFolder =
    feedFilter === "all" && folderIdentifier && subscriptionsData
      ? subscriptionsData.folders.find(
          (folder) => folder.folderIdentifier === folderIdentifier
        )
      : undefined

  const matchingCustomFeed =
    feedFilter === "all" && customFeedIdentifier && customFeedsData
      ? customFeedsData.find(
          (customFeed) => customFeed.identifier === customFeedIdentifier
        )
      : undefined

  if (matchingCustomFeed) {
    pageTitle = matchingCustomFeed.name
    isRenameable = true
  }

  if (matchingSubscription) {
    pageTitle =
      matchingSubscription.customTitle ||
      matchingSubscription.feedTitle ||
      "feed"
    isRenameable = true
  }

  if (matchingFolder) {
    pageTitle = matchingFolder.name
    isRenameable = true
  }

  function handleStartRename() {
    setRenameValue(pageTitle)
    setIsRenamingTitle(true)
  }

  function handleSaveRename() {
    const trimmedValue = renameValue.trim()
    if (!trimmedValue || trimmedValue === pageTitle) {
      setIsRenamingTitle(false)
      return
    }

    if (matchingSubscription) {
      updateSubscriptionTitle.mutate({
        subscriptionIdentifier: matchingSubscription.subscriptionIdentifier,
        customTitle: trimmedValue,
      })
    } else if (matchingFolder) {
      renameFolder.mutate({
        folderIdentifier: matchingFolder.folderIdentifier,
        name: trimmedValue,
      })
    } else if (matchingCustomFeed) {
      updateCustomFeed.mutate({
        customFeedIdentifier: matchingCustomFeed.identifier,
        name: trimmedValue,
        query: matchingCustomFeed.query,
        matchMode: matchingCustomFeed.matchMode,
        sourceFolderIdentifier: matchingCustomFeed.sourceFolderIdentifier,
      })
    }

    setIsRenamingTitle(false)
  }

  const totalUnreadCount = Object.values(unreadCounts ?? {}).reduce(
    (sum, count) => sum + count,
    0
  )
  const allAreRead = totalUnreadCount === 0

  const toolbar = (
    <header className={classNames(
      "flex items-center justify-between border-border px-4 py-3",
      toolbarPosition === "top" ? "border-b" : "border-t"
    )}>
      {isMobile && selectedEntryIdentifier ? (() => {
        const currentIndex = navigableEntryIdentifiers.indexOf(selectedEntryIdentifier)
        const previousEntryIdentifier = currentIndex > 0 ? navigableEntryIdentifiers[currentIndex - 1] : null
        const nextEntryIdentifier = currentIndex < navigableEntryIdentifiers.length - 1 ? navigableEntryIdentifiers[currentIndex + 1] : null

        return (
          <div className="flex items-center gap-3">
            <button
              type="button"
              onClick={() => setSelectedEntryIdentifier(null)}
              className="text-text-secondary transition-colors hover:text-text-primary"
            >
              &larr; back
            </button>
            <button
              type="button"
              onClick={() => previousEntryIdentifier && setSelectedEntryIdentifier(previousEntryIdentifier)}
              disabled={!previousEntryIdentifier}
              className="text-text-secondary transition-colors hover:text-text-primary disabled:opacity-30"
            >
              &uarr; previous
            </button>
            <button
              type="button"
              onClick={() => nextEntryIdentifier && setSelectedEntryIdentifier(nextEntryIdentifier)}
              disabled={!nextEntryIdentifier}
              className="text-text-secondary transition-colors hover:text-text-primary disabled:opacity-30"
            >
              &darr; next
            </button>
          </div>
        )
      })() : isRenamingTitle ? (
        <div className="flex items-center gap-2">
          <input
            type="text"
            value={renameValue}
            onChange={(event) => setRenameValue(event.target.value)}
            onKeyDown={(event) => {
              if (event.key === "Enter") handleSaveRename()
              if (event.key === "Escape") setIsRenamingTitle(false)
            }}
            className="min-w-0 border border-border bg-background-primary px-2 py-1 text-text-primary outline-none focus:border-text-dim"
            autoFocus
          />
          <button
            type="button"
            onClick={handleSaveRename}
            className="text-text-secondary transition-colors hover:text-text-primary"
          >
            save
          </button>
          <button
            type="button"
            onClick={() => setIsRenamingTitle(false)}
            className="text-text-secondary transition-colors hover:text-text-primary"
          >
            cancel
          </button>
        </div>
      ) : (
        <div className="flex items-center gap-2">
          <h1 className="text-text-primary">{pageTitle}</h1>
          {isRenameable && (
            <button
              type="button"
              onClick={handleStartRename}
              className="text-text-dim transition-colors hover:text-text-secondary"
            >
              rename
            </button>
          )}
        </div>
      )}
      <div className="flex items-center gap-3">
        {!(isMobile && selectedEntryIdentifier) && (
          <>
            <button
              type="button"
              onClick={() => setSearchOpen(true)}
              className="text-text-dim transition-colors hover:text-text-secondary"
            >
              search
            </button>
            {feedFilter === "all" && (
              <button
                type="button"
                onClick={() =>
                  markAllAsRead.mutate({ feedIdentifier, folderIdentifier, readState: !allAreRead })
                }
                disabled={markAllAsRead.isPending}
                className="text-text-dim transition-colors hover:text-text-secondary disabled:opacity-50"
              >
                {allAreRead ? "mark all unread" : "mark all read"}
              </button>
            )}
            <select
              value={entryListViewMode}
              onChange={(event) =>
                setEntryListViewMode(
                  event.target.value as "compact" | "comfortable" | "expanded"
                )
              }
              className="hidden border border-border bg-background-primary px-2 py-1 text-text-secondary outline-none sm:block"
            >
              <option value="compact">compact</option>
              <option value="comfortable">comfortable</option>
              <option value="expanded">expanded</option>
            </select>
            <button
              type="button"
              onClick={() => toggleShortcutsDialog()}
              className="hidden text-text-dim transition-colors hover:text-text-secondary sm:block"
            >
              shortcuts
            </button>
          </>
        )}
      </div>
    </header>
  )

  return (
    <div className="flex h-full flex-col">
      {toolbarPosition === "top" && toolbar}
      <div className="relative min-h-0 flex-1">
      <ErrorBoundary>
        {isMobile ? (
          <>
            <div className={classNames(
              "absolute inset-0 overflow-x-hidden overflow-y-hidden",
              selectedEntryIdentifier ? "invisible" : "visible"
            )}>
              <ErrorBoundary>
                <EntryList
                  feedFilter={feedFilter}
                  folderIdentifier={folderIdentifier}
                  feedIdentifier={feedIdentifier}
                  customFeedIdentifier={customFeedIdentifier}
                />
              </ErrorBoundary>
            </div>
            {selectedEntryIdentifier && (
              <div className="absolute inset-0 overflow-hidden bg-background-primary">
                <ErrorBoundary>
                  <EntryDetailPanel
                    entryIdentifier={selectedEntryIdentifier}
                  />
                </ErrorBoundary>
              </div>
            )}
          </>
        ) : (
          <Group
            orientation="horizontal"
            className="min-h-0 flex-1"
            defaultLayout={detailLayout.defaultLayout}
            onLayoutChanged={detailLayout.onLayoutChanged}
            groupRef={detailGroupRef}
          >
            <Panel id="entry-list" defaultSize={selectedEntryIdentifier ? "40%" : "100%"} minSize="25%">
              <div data-panel-zone="entryList" className={classNames(
                "h-full",
                focusedPanel === "entryList" ? "border-t-2 border-t-text-dim" : "border-t-2 border-t-transparent"
              )}>
                <ErrorBoundary>
                  <EntryList
                    feedFilter={feedFilter}
                    folderIdentifier={folderIdentifier}
                    feedIdentifier={feedIdentifier}
                    customFeedIdentifier={customFeedIdentifier}
                  />
                </ErrorBoundary>
              </div>
            </Panel>
            {selectedEntryIdentifier && (
              <>
                <Separator className="w-px bg-border transition-colors hover:bg-text-dim" />
                <Panel id="detail-panel" defaultSize="60%" minSize="30%">
                  <div data-panel-zone="detailPanel" className={classNames(
                    "h-full overflow-hidden",
                    focusedPanel === "detailPanel" ? "border-t-2 border-t-text-dim" : "border-t-2 border-t-transparent"
                  )}>
                    <ErrorBoundary>
                      <EntryDetailPanel
                        entryIdentifier={selectedEntryIdentifier}
                      />
                    </ErrorBoundary>
                  </div>
                </Panel>
              </>
            )}
          </Group>
        )}
      </ErrorBoundary>
      </div>
      {toolbarPosition === "bottom" && toolbar}
    </div>
  )
}
