"use client"

import { useState, useRef, useEffect, useMemo } from "react"
import { useIsXs } from "@/hooks/use-xs"
import { useTouchNav } from "@/hooks/use-touch-nav"
import { readTouchNavMatches } from "@/hooks/use-touch-nav"
import { isSystemNavLabelId } from "@/lib/sidebar-nav-data"
import { useSidebarNav } from "@/lib/sidebar-nav-context"
import { ancestorFolderIdsForTarget } from "@/lib/sidebar-folder-tree-utils"
import {
  mainItems,
  CATEGORY_IDS_IN_PLUS_ONLY,
  sortSystemLabelRows,
} from "@/components/gmail/sidebar/sidebar-nav-constants"
import { folderParentSelectOptions } from "@/components/gmail/sidebar/sidebar-nav-primitives"
import { useSidebarNavDrag } from "@/hooks/use-sidebar-nav-drag"
import {
  MAIL_SIDEBAR_PANEL_SURFACE_CLASS,
  MAIL_SIDEBAR_PANEL_SURFACE_MOBILE_CLASS,
} from "@/lib/mail-chrome-classes"

export interface SidebarProps {
  selectedFolder: string
  onSelectFolder: (folder: string) => void
  collapsed: boolean
  folderUnreadCounts?: Record<string, number>
  splitView?: boolean
}

export function useSidebarState({
  selectedFolder,
  onSelectFolder,
  collapsed,
  folderUnreadCounts = {},
}: SidebarProps) {
  const [hoverExpanded, setHoverExpanded] = useState(false)
  const [navMoreOpen, setNavMoreOpen] = useState(false)
  const [expandedFolderIds, setExpandedFolderIds] = useState<Set<string>>(() => new Set())
  const hoverTimeoutRef = useRef<NodeJS.Timeout | null>(null)
  const sidebarRef = useRef<HTMLElement>(null)
  const touchNav = useTouchNav()
  const isXs = useIsXs()

  const isExpanded = !collapsed || (!touchNav && hoverExpanded)
  const isOverlayOpen = touchNav && !collapsed

  const nav = useSidebarNav()
  const {
    folderTree,
    labelRows,
    folderIdToLabel,
    addFolder,
    addLabelRowFromSidebar,
    getNavItemPrefs,
    setNavItemSidebarVisibility,
    setNavItemMessageVisibility,
    updateFolderOrLabelColor,
    renameFolderOrLabel,
    removeFolderOrLabelRow,
    moveFolder,
    reorderLabelRows,
    moveFolderRelative,
    addSubfolder,
    addChildLabelRow,
    setLabelRowEnabled,
  } = nav

  const drag = useSidebarNavDrag({
    reorderLabelRows,
    moveFolderRelative,
    setExpandedFolderIds,
  })

  const visibleNavLabelRows = useMemo(() => {
    return labelRows.filter((row) => {
      if (row.enabled === false) return false
      if (isSystemNavLabelId(row.id)) return false
      const p = getNavItemPrefs(row.id)
      if (p.sidebar === "hide") return false
      if (
        p.sidebar === "showUnread" &&
        (folderUnreadCounts[row.id] ?? 0) === 0
      ) {
        return false
      }
      return true
    })
  }, [labelRows, getNavItemPrefs, folderUnreadCounts])

  const validNavFolderIds = useMemo(() => {
    const s = new Set<string>()
    for (const i of mainItems) s.add(i.id)
    for (const k of Object.keys(folderIdToLabel)) s.add(k)
    return s
  }, [folderIdToLabel])

  useEffect(() => {
    if (selectedFolder !== "search" && !validNavFolderIds.has(selectedFolder)) {
      onSelectFolder("inbox")
    }
  }, [validNavFolderIds, selectedFolder, onSelectFolder])

  const [folderDialogOpen, setFolderDialogOpen] = useState(false)
  const [labelDialogOpen, setLabelDialogOpen] = useState(false)
  const [newFolderName, setNewFolderName] = useState("")
  const [newFolderParent, setNewFolderParent] = useState("__root__")
  const [newLabelName, setNewLabelName] = useState("")
  const newFolderNameInputRef = useRef<HTMLInputElement>(null)
  const newLabelNameInputRef = useRef<HTMLInputElement>(null)

  const folderParentOptions = useMemo(
    () => folderParentSelectOptions(folderTree),
    [folderTree]
  )

  const { primaryVisibleCategories, plusOnlyVisibleCategories } = useMemo(() => {
    const systemEnabled = sortSystemLabelRows(
      labelRows.filter((r) => r.enabled !== false && isSystemNavLabelId(r.id))
    ).map((r) => ({ id: r.id, label: r.label, icon: r.icon }))
    return {
      primaryVisibleCategories: systemEnabled.filter(
        (c) => !CATEGORY_IDS_IN_PLUS_ONLY.has(c.id)
      ),
      plusOnlyVisibleCategories: systemEnabled.filter((c) =>
        CATEGORY_IDS_IN_PLUS_ONLY.has(c.id)
      ),
    }
  }, [labelRows])

  const disabledSystemNavItems = useMemo(() => {
    return sortSystemLabelRows(
      labelRows.filter((r) => r.enabled === false && isSystemNavLabelId(r.id))
    ).map((r) => ({ id: r.id, label: r.label, icon: r.icon }))
  }, [labelRows])

  const visibleMainItems = useMemo(() => {
    const scheduledTotal = folderUnreadCounts.scheduled ?? 0
    if (scheduledTotal > 0) return mainItems
    return mainItems.filter((item) => item.id !== "scheduled")
  }, [folderUnreadCounts.scheduled])

  const toggleFolderExpanded = (id: string) => {
    setExpandedFolderIds((prev) => {
      const next = new Set(prev)
      if (next.has(id)) next.delete(id)
      else next.add(id)
      return next
    })
  }

  const handleSubmitNewFolder = () => {
    const name = newFolderName.trim()
    if (!name) return
    const parentId = newFolderParent === "__root__" ? null : newFolderParent
    addFolder(parentId, name)
    setNewFolderName("")
    setFolderDialogOpen(false)
  }

  const handleSubmitNewLabel = () => {
    const name = newLabelName.trim()
    if (!name) return
    addLabelRowFromSidebar(name)
    setNewLabelName("")
    setLabelDialogOpen(false)
  }

  useEffect(() => {
    const row = labelRows.find((r) => r.id === selectedFolder)
    if (row && row.enabled === false) {
      onSelectFolder("inbox")
    }
  }, [labelRows, selectedFolder, onSelectFolder])

  useEffect(() => {
    if (selectedFolder !== "scheduled") return
    if ((folderUnreadCounts.scheduled ?? 0) > 0) return
    onSelectFolder("inbox")
  }, [folderUnreadCounts.scheduled, selectedFolder, onSelectFolder])

  useEffect(() => {
    if (CATEGORY_IDS_IN_PLUS_ONLY.has(selectedFolder) && !navMoreOpen) {
      setNavMoreOpen(true)
    }
  }, [selectedFolder, navMoreOpen])

  useEffect(() => {
    const ancestors = ancestorFolderIdsForTarget(folderTree, selectedFolder)
    if (ancestors?.length) {
      setExpandedFolderIds((prev) => {
        const next = new Set(prev)
        ancestors.forEach((id) => next.add(id))
        return next
      })
    }
  }, [selectedFolder, folderTree])

  const handleMouseEnter = () => {
    if (readTouchNavMatches()) return
    if (collapsed) {
      hoverTimeoutRef.current = setTimeout(() => {
        setHoverExpanded(true)
      }, 300)
    }
  }

  const handleMouseLeave = () => {
    if (hoverTimeoutRef.current) {
      clearTimeout(hoverTimeoutRef.current)
      hoverTimeoutRef.current = null
    }
    if (readTouchNavMatches()) return
    setHoverExpanded(false)
  }

  useEffect(() => {
    if (touchNav) setHoverExpanded(false)
  }, [touchNav, collapsed])

  useEffect(() => {
    return () => {
      if (hoverTimeoutRef.current) {
        clearTimeout(hoverTimeoutRef.current)
      }
    }
  }, [])

  const navRailInset = "pr-3.5"
  const splitViewLogoIconClass = "size-9 shrink-0"
  const splitViewLogoHeaderClass =
    "box-border min-h-[80px] pt-3 pl-4 pr-3.5 pb-4"

  const navDragBindings = useMemo(
    () => ({
      navDragRef: drag.navDragRef,
      navDropPlacementRef: drag.navDropPlacementRef,
      beginNavDrag: drag.beginNavDrag,
      clearNavDrag: drag.clearNavDrag,
      updateNavDropTarget: drag.updateNavDropTarget,
      clearNavDropTarget: drag.clearNavDropTarget,
      commitNavDrop: drag.commitNavDrop,
    }),
    [drag]
  )

  const folderRowProps = useMemo(
    () => ({
      ...navDragBindings,
      selectedFolder,
      folderUnreadCounts,
      expandedFolderIds,
      isExpanded,
      isOverlayOpen,
      touchNav,
      folderTree,
      onSelectFolder,
      toggleFolderExpanded,
      getNavItemPrefs,
      setNavItemSidebarVisibility,
      setNavItemMessageVisibility,
      updateFolderOrLabelColor,
      renameFolderOrLabel,
      removeFolderOrLabelRow,
      moveFolder,
      addSubfolder,
    }),
    [
      navDragBindings,
      selectedFolder,
      folderUnreadCounts,
      expandedFolderIds,
      isExpanded,
      isOverlayOpen,
      touchNav,
      folderTree,
      onSelectFolder,
      getNavItemPrefs,
      setNavItemSidebarVisibility,
      setNavItemMessageVisibility,
      updateFolderOrLabelColor,
      renameFolderOrLabel,
      removeFolderOrLabelRow,
      moveFolder,
      addSubfolder,
    ]
  )

  const collapsedFolderOpts = useMemo(
    () => ({
      getNavItemPrefs,
      folderUnreadCounts,
      expandedFolderIds,
      isExpanded,
      selectedFolder,
      onSelectFolder,
    }),
    [
      getNavItemPrefs,
      folderUnreadCounts,
      expandedFolderIds,
      isExpanded,
      selectedFolder,
      onSelectFolder,
    ]
  )

  const labelRowProps = useMemo(
    () => ({
      ...navDragBindings,
      selectedFolder,
      touchNav,
      onSelectFolder,
      getNavItemPrefs,
      setNavItemSidebarVisibility,
      setNavItemMessageVisibility,
      updateFolderOrLabelColor,
      renameFolderOrLabel,
      removeFolderOrLabelRow,
      addChildLabelRow,
    }),
    [
      navDragBindings,
      selectedFolder,
      touchNav,
      onSelectFolder,
      getNavItemPrefs,
      setNavItemSidebarVisibility,
      setNavItemMessageVisibility,
      updateFolderOrLabelColor,
      renameFolderOrLabel,
      removeFolderOrLabelRow,
      addChildLabelRow,
    ]
  )

  const panelSurfaceClass =
    isOverlayOpen && isXs
      ? MAIL_SIDEBAR_PANEL_SURFACE_MOBILE_CLASS
      : MAIL_SIDEBAR_PANEL_SURFACE_CLASS

  return {
    sidebarRef,
    touchNav,
    hoverExpanded,
    isExpanded,
    isOverlayOpen,
    panelSurfaceClass,
    navRailInset,
    splitViewLogoIconClass,
    splitViewLogoHeaderClass,
    handleMouseEnter,
    handleMouseLeave,
    navMoreOpen,
    setNavMoreOpen,
    visibleMainItems,
    primaryVisibleCategories,
    plusOnlyVisibleCategories,
    disabledSystemNavItems,
    folderTree,
    folderRowProps,
    collapsedFolderOpts,
    visibleNavLabelRows,
    labelRowProps,
    setLabelRowEnabled,
    folderDialogOpen,
    setFolderDialogOpen,
    labelDialogOpen,
    setLabelDialogOpen,
    newFolderName,
    setNewFolderName,
    newFolderParent,
    setNewFolderParent,
    newLabelName,
    setNewLabelName,
    newFolderNameInputRef,
    newLabelNameInputRef,
    folderParentOptions,
    handleSubmitNewFolder,
    handleSubmitNewLabel,
  }
}
