"use client"

import * as React from "react"
import { usePathname, useRouter, useSearchParams } from "@/lib/next-compat"

import { useSecondaryPanel } from "@/components/sidebar"
import { LIBRARY_HUB_FIND_PATH, LIBRARY_ALL_PATH, LIBRARY_LIST_PATH } from "@/lib/library-nav"

function rewriteLibraryCanonicalToDedicatedSurface(pathname: string, nextHref: string, hash: string): string {
  if (!nextHref.startsWith(LIBRARY_ALL_PATH)) return `${nextHref}${hash}`
  const tail = nextHref.slice(LIBRARY_ALL_PATH.length)
  if (pathname === LIBRARY_LIST_PATH) return `${LIBRARY_LIST_PATH}${tail}${hash}`
  if (pathname === LIBRARY_HUB_FIND_PATH) return `${LIBRARY_HUB_FIND_PATH}${tail}${hash}`
  return `${nextHref}${hash}`
}

function librarySearchParamsEqual(a: URLSearchParams, b: URLSearchParams): boolean {
  const keys = new Set([...a.keys(), ...b.keys()])
  for (const k of keys) {
    const av = a.getAll(k).join("\u0000")
    const bv = b.getAll(k).join("\u0000")
    if (av !== bv) return false
  }
  return true
}

export interface UseSecondaryPanelHubNavOptions<TNav> {
  /** Primary hub pathname (e.g. `/library/all`). */
  hubPathname: string
  /** When set, these pathnames are treated as the same hub (e.g. library + list search surface). */
  hubPathnames?: readonly string[]
  /** `PANELS` / `useAutoPanel` id (e.g. `library`). */
  panelId: string
  parseNav: (searchParams: URLSearchParams) => TNav
  /** When non-null, the hub URL is rewritten (keeps the current hash). */
  canonicalHref?: (searchParams: URLSearchParams) => string | null
  /** Re-open the secondary panel when the user returns to the default scope (e.g. All questions). */
  shouldReopenPanel?: (nav: TNav) => boolean
  /**
   * When set, auto-reopen only runs on these pathnames (e.g. library hub, not dedicated search landings).
   * Omit to keep legacy behavior: any {@link hubPathnames} match may reopen the panel.
   */
  reopenPanelOnPathnames?: readonly string[]
}

/**
 * URL scope for a primary hub with a nested secondary panel — shared between panel nav and main content.
 */
export function useSecondaryPanelHubNav<TNav>({
  hubPathname,
  hubPathnames,
  panelId,
  parseNav,
  canonicalHref,
  shouldReopenPanel,
  reopenPanelOnPathnames,
}: UseSecondaryPanelHubNavOptions<TNav>) {
  const pathname = usePathname()
  const router = useRouter()
  const searchParams = useSearchParams()
  const { openPanel, activePanel } = useSecondaryPanel()

  const hubPaths = React.useMemo(
    () => (hubPathnames?.length ? [...hubPathnames] : [hubPathname]),
    [hubPathname, hubPathnames],
  )
  const isHubPath = hubPaths.includes(pathname)
  const hubBasePath = hubPaths.includes(pathname) ? pathname : hubPathname

  const searchParamsKey = searchParams.toString()
  const navState = React.useMemo(
    () => parseNav(new URLSearchParams(searchParamsKey)),
    [parseNav, searchParamsKey],
  )

  React.useEffect(() => {
    if (!isHubPath || !canonicalHref) return
    const nextHref = canonicalHref(new URLSearchParams(searchParamsKey))
    if (!nextHref) return
    const hash = typeof window !== "undefined" ? window.location.hash : ""
    let target = `${nextHref}${hash}`
    if (pathname === LIBRARY_LIST_PATH || pathname === LIBRARY_HUB_FIND_PATH) {
      target = rewriteLibraryCanonicalToDedicatedSurface(pathname, nextHref, hash)
    }
    try {
      const origin = typeof window !== "undefined" ? window.location.origin : "http://localhost"
      const u = new URL(target, origin)
      const want = u.searchParams
      const cur = new URLSearchParams(searchParamsKey)
      if (u.pathname === pathname && librarySearchParamsEqual(want, cur)) return
    } catch {
      /* ignore parse errors — fall through to replace */
    }
    router.replace(target, { scroll: false })
  }, [canonicalHref, isHubPath, pathname, router, searchParamsKey])

  React.useEffect(() => {
    if (!isHubPath || !shouldReopenPanel?.(navState)) return
    if (reopenPanelOnPathnames?.length && !reopenPanelOnPathnames.includes(pathname)) return
    if (activePanel === panelId) return
    openPanel(panelId)
  }, [
    activePanel,
    isHubPath,
    navState,
    openPanel,
    panelId,
    pathname,
    reopenPanelOnPathnames,
    shouldReopenPanel,
  ])

  return { navState, searchParamsKey, hubPathname, hubBasePath, pathname, isHubPath }
}
