"use client"

import { Suspense, useEffect, useMemo, useRef, useState } from "react"
import { Group, Panel, Separator, useDefaultLayout, useGroupRef } from "react-resizable-panels"
import { useUserInterfaceStore } from "@/lib/stores/user-interface-store"
import { classNames } from "@/lib/utilities"
import { useIsMobile } from "@/lib/hooks/use-is-mobile"
import { ErrorBoundary } from "./error-boundary"
import { SidebarContent } from "./sidebar-content"
import { CommandPalette } from "./command-palette"
import { AddFeedDialog } from "./add-feed-dialog"
import { SearchOverlay } from "./search-overlay"
import { KeyboardShortcutsDialog } from "./keyboard-shortcuts-dialog"
import { MfaChallenge } from "./mfa-challenge"
import { useKeyboardNavigation } from "@/lib/hooks/use-keyboard-navigation"
import { createSupabaseBrowserClient } from "@/lib/supabase/client"
import { useSubscriptions } from "@/lib/queries/use-subscriptions"
import { useCustomFeeds } from "@/lib/queries/use-custom-feeds"
import { useUserProfile } from "@/lib/queries/use-user-profile"

const DENSITY_FONT_SIZE_MAP: Record<string, string> = {
  compact: "0.875rem",
  default: "1rem",
  spacious: "1.125rem",
}

export function ReaderLayoutShell({
  sidebarFooter,
  children,
}: {
  sidebarFooter: React.ReactNode
  children: React.ReactNode
}) {
  const [requiresMfaVerification, setRequiresMfaVerification] = useState(false)
  const [isMfaCheckComplete, setIsMfaCheckComplete] = useState(false)

  const isSidebarCollapsed = useUserInterfaceStore(
    (state) => state.isSidebarCollapsed
  )
  const toggleSidebar = useUserInterfaceStore((state) => state.toggleSidebar)
  const setSidebarCollapsed = useUserInterfaceStore(
    (state) => state.setSidebarCollapsed
  )
  const displayDensity = useUserInterfaceStore(
    (state) => state.displayDensity
  )
  const isSearchOpen = useUserInterfaceStore((state) => state.isSearchOpen)
  const setSearchOpen = useUserInterfaceStore((state) => state.setSearchOpen)
  const focusedPanel = useUserInterfaceStore((state) => state.focusedPanel)
  const focusFollowsInteraction = useUserInterfaceStore(
    (state) => state.focusFollowsInteraction
  )
  const isMobile = useIsMobile()
  const showFeedFavicons = useUserInterfaceStore(
    (state) => state.showFeedFavicons
  )
  const { data: subscriptionsData } = useSubscriptions()
  const { data: customFeedsData } = useCustomFeeds()
  const { data: userProfile } = useUserProfile()

  const sidebarMaxWidth = useMemo(() => {
    if (typeof window === "undefined") return "35%"
    if (!subscriptionsData || !customFeedsData) return "35%"

    const canvas = document.createElement("canvas")
    const maybeContext = canvas.getContext("2d")
    if (!maybeContext) return "35%"

    const canvasContext = maybeContext
    const computedStyle = window.getComputedStyle(document.body)
    const fontFamily = computedStyle.fontFamily
    const baseFontSizePixels = parseFloat(computedStyle.fontSize)
    const feedFontSizePixels = baseFontSizePixels * 0.85

    function measureText(text: string, fontSize: number): number {
      canvasContext.font = `${fontSize}px ${fontFamily}`
      return canvasContext.measureText(text).width
    }

    let maximumItemWidth = 0

    const faviconSpace = showFeedFavicons ? 24 : 0
    const NAV_PADDING = 32
    const FEED_PADDING = 40
    const FOLDER_FEED_PADDING = 48
    const FOLDER_PADDING = 46
    const FOOTER_PADDING = 32
    const BADGE_SPACE = 40
    const NOTIFICATION_BADGE_SPACE = 28
    const SCROLLBAR_WIDTH = 8

    for (const label of ["all entries", "saved", "highlights", "shares"]) {
      maximumItemWidth = Math.max(
        maximumItemWidth,
        NAV_PADDING + measureText(label, baseFontSizePixels) + BADGE_SPACE
      )
    }
    maximumItemWidth = Math.max(
      maximumItemWidth,
      NAV_PADDING + measureText("+ add feed", baseFontSizePixels)
    )

    if (customFeedsData) {
      for (const customFeed of customFeedsData) {
        const iconSpace = customFeed.iconUrl ? 24 : 0
        maximumItemWidth = Math.max(
          maximumItemWidth,
          FEED_PADDING + iconSpace + measureText(customFeed.name, feedFontSizePixels)
        )
      }
    }

    const subscriptions = subscriptionsData?.subscriptions ?? []
    const folders = subscriptionsData?.folders ?? []

    for (const subscription of subscriptions) {
      const name = subscription.customTitle || subscription.feedTitle || "untitled"
      const indent = subscription.folderIdentifier ? FOLDER_FEED_PADDING : FEED_PADDING
      const extras =
        faviconSpace +
        (subscription.feedType === "podcast" ? 14 : 0) +
        (subscription.consecutiveFailures > 0 ? 24 : 0) +
        BADGE_SPACE
      maximumItemWidth = Math.max(
        maximumItemWidth,
        indent + extras + measureText(name, feedFontSizePixels)
      )
    }

    for (const folder of folders) {
      const iconSpace = folder.iconUrl ? 24 : 0
      maximumItemWidth = Math.max(
        maximumItemWidth,
        FOLDER_PADDING + iconSpace + measureText(folder.name, baseFontSizePixels) + BADGE_SPACE
      )
    }

    const displayName = userProfile?.displayName ?? "account"
    for (const label of [displayName, "settings", "sign out"]) {
      maximumItemWidth = Math.max(
        maximumItemWidth,
        FOOTER_PADDING + measureText(label, baseFontSizePixels)
      )
    }
    maximumItemWidth = Math.max(
      maximumItemWidth,
      FOOTER_PADDING + measureText("notifications", baseFontSizePixels) + NOTIFICATION_BADGE_SPACE
    )

    maximumItemWidth += SCROLLBAR_WIDTH
    maximumItemWidth = Math.max(maximumItemWidth, 192)

    return `${Math.ceil(maximumItemWidth)}px`
  }, [subscriptionsData, customFeedsData, userProfile, displayDensity, showFeedFavicons])

  const sidebarLayout = useDefaultLayout({
    id: "asa-sidebar-layout",
    panelIds: ["sidebar", "main-content"],
    storage: typeof window !== "undefined" ? localStorage : { getItem: () => null, setItem: () => {} },
  })

  const sidebarGroupRef = useGroupRef()
  const sidebarMaxWidthRef = useRef(sidebarMaxWidth)
  sidebarMaxWidthRef.current = sidebarMaxWidth
  const sidebarOnLayoutChangedRef = useRef(sidebarLayout.onLayoutChanged)
  sidebarOnLayoutChangedRef.current = sidebarLayout.onLayoutChanged

  useEffect(() => {
    useUserInterfaceStore.getState().setResetSidebarLayout(() => {
      const group = sidebarGroupRef.current
      if (!group) return
      const groupElement = document.querySelector("[data-group]") as HTMLElement | null
      if (!groupElement) return
      const totalPixels = groupElement.offsetWidth
      if (totalPixels === 0) return
      const minPixels = 192
      const maxWidthValue = sidebarMaxWidthRef.current
      let maxPixels: number
      if (maxWidthValue.endsWith("px")) {
        maxPixels = parseFloat(maxWidthValue)
      } else if (maxWidthValue.endsWith("%")) {
        maxPixels = totalPixels * parseFloat(maxWidthValue) / 100
      } else {
        maxPixels = totalPixels * 0.35
      }
      const midpointPixels = Math.round((minPixels + maxPixels) / 2)
      const midpointPercent = (midpointPixels / totalPixels) * 100
      const appliedLayout = group.setLayout({
        sidebar: midpointPercent,
        "main-content": 100 - midpointPercent,
      })
      sidebarOnLayoutChangedRef.current?.(appliedLayout)
    })
    return () => useUserInterfaceStore.getState().setResetSidebarLayout(null)
  }, [sidebarGroupRef])

  useKeyboardNavigation()

  useEffect(() => {
    async function checkAssuranceLevel() {
      const supabaseClient = createSupabaseBrowserClient()
      const { data } = await supabaseClient.auth.mfa.getAuthenticatorAssuranceLevel()

      if (
        data &&
        data.currentLevel === "aal1" &&
        data.nextLevel === "aal2"
      ) {
        setRequiresMfaVerification(true)
      }

      setIsMfaCheckComplete(true)
    }

    checkAssuranceLevel()
  }, [])

  useEffect(() => {
    if (window.innerWidth < 768) {
      setSidebarCollapsed(true)
    }
  }, [setSidebarCollapsed])

  useEffect(() => {
    document.body.style.setProperty(
      "--base-font-size",
      DENSITY_FONT_SIZE_MAP[displayDensity] ?? "0.8125rem"
    )
  }, [displayDensity])

  useEffect(() => {
    if (!focusFollowsInteraction) return

    function handlePointerDown(event: PointerEvent) {
      const target = event.target as HTMLElement
      const zone = target.closest("[data-panel-zone]")
      if (!zone) return
      const panelZone = zone.getAttribute("data-panel-zone")
      if (
        panelZone === "sidebar" ||
        panelZone === "entryList" ||
        panelZone === "detailPanel"
      ) {
        useUserInterfaceStore.getState().setFocusedPanel(panelZone)
      }
    }

    function handleScroll(event: Event) {
      const target = event.target as HTMLElement
      if (!target || !target.closest) return
      const zone = target.closest("[data-panel-zone]")
      if (!zone) return
      const panelZone = zone.getAttribute("data-panel-zone")
      if (
        panelZone === "sidebar" ||
        panelZone === "entryList" ||
        panelZone === "detailPanel"
      ) {
        const currentPanel = useUserInterfaceStore.getState().focusedPanel
        if (currentPanel !== panelZone) {
          useUserInterfaceStore.getState().setFocusedPanel(panelZone)
        }
      }
    }

    document.addEventListener("pointerdown", handlePointerDown)
    document.addEventListener("scroll", handleScroll, true)
    return () => {
      document.removeEventListener("pointerdown", handlePointerDown)
      document.removeEventListener("scroll", handleScroll, true)
    }
  }, [focusFollowsInteraction])

  if (!isMfaCheckComplete) {
    return (
      <div className="flex h-screen items-center justify-center bg-background-primary">
        <span className="text-text-dim">loading ...</span>
      </div>
    )
  }

  if (requiresMfaVerification) {
    return <MfaChallenge onVerified={() => setRequiresMfaVerification(false)} />
  }

  return (
    <div className="flex h-screen">
      {isMobile ? (
        <>
          <div
            className={classNames(
              "fixed inset-0 z-30 bg-black/50 transition-opacity",
              !isSidebarCollapsed
                ? "pointer-events-auto opacity-100"
                : "pointer-events-none opacity-0"
            )}
            onClick={toggleSidebar}
          />
          <aside
            data-panel-zone="sidebar"
            className={classNames(
              "fixed z-40 flex h-full w-64 shrink-0 flex-col border-r border-border bg-background-secondary transition-transform duration-200",
              isSidebarCollapsed ? "-translate-x-full" : "translate-x-0"
            )}
          >
            <div className="flex items-center justify-between p-4">
              <h2 className="text-text-primary">asa.news</h2>
              <button
                type="button"
                onClick={toggleSidebar}
                className="px-1 py-0.5 text-lg leading-none text-text-dim transition-colors hover:text-text-secondary"
              >
                &times;
              </button>
            </div>
            <ErrorBoundary>
              <Suspense>
                <SidebarContent />
              </Suspense>
            </ErrorBoundary>
            {sidebarFooter}
          </aside>
          <main className="flex-1 overflow-hidden">
            <div className="flex h-full flex-col">
              {isSidebarCollapsed && (
                <div className="flex items-center border-b border-border px-2 py-1">
                  <button
                    type="button"
                    onClick={toggleSidebar}
                    className="px-2 py-1 text-lg leading-none text-text-secondary transition-colors hover:text-text-primary"
                  >
                    &#9776;
                  </button>
                </div>
              )}
              <div className="flex-1 overflow-hidden">{children}</div>
            </div>
          </main>
        </>
      ) : (
        <div className="flex-1 overflow-hidden">
          <Group
            orientation="horizontal"
            defaultLayout={sidebarLayout.defaultLayout}
            onLayoutChanged={isSidebarCollapsed ? undefined : sidebarLayout.onLayoutChanged}
            groupRef={sidebarGroupRef}
          >
            {!isSidebarCollapsed && (
              <>
                <Panel id="sidebar" defaultSize="16rem" minSize="12rem" maxSize={sidebarMaxWidth}>
                  <aside
                    data-panel-zone="sidebar"
                    className={classNames(
                      "flex h-full flex-col border-r border-border bg-background-secondary",
                      focusedPanel === "sidebar"
                        ? "border-r-text-dim"
                        : ""
                    )}
                  >
                    <div className="flex items-center justify-between p-4">
                      <h2 className="text-text-primary">asa.news</h2>
                      <button
                        type="button"
                        onClick={toggleSidebar}
                        className="px-1 py-0.5 text-lg leading-none text-text-dim transition-colors hover:text-text-secondary"
                      >
                        &times;
                      </button>
                    </div>
                    <ErrorBoundary>
                      <Suspense>
                        <SidebarContent />
                      </Suspense>
                    </ErrorBoundary>
                    {sidebarFooter}
                  </aside>
                </Panel>
                <Separator className="w-px bg-border transition-colors hover:bg-text-dim" />
              </>
            )}
            <Panel id="main-content">
              <main className="h-full overflow-hidden">
                <div className="flex h-full flex-col">
                  {isSidebarCollapsed && (
                    <div className="flex items-center border-b border-border px-2 py-1">
                      <button
                        type="button"
                        onClick={toggleSidebar}
                        className="px-2 py-1 text-lg leading-none text-text-secondary transition-colors hover:text-text-primary"
                      >
                        &#9776;
                      </button>
                    </div>
                  )}
                  <div className="flex-1 overflow-hidden">{children}</div>
                </div>
              </main>
            </Panel>
          </Group>
        </div>
      )}
      <CommandPalette />
      <AddFeedDialog />
      {isSearchOpen && (
        <SearchOverlay onClose={() => setSearchOpen(false)} />
      )}
      <KeyboardShortcutsDialog />
    </div>
  )
}
