import { useMemo, useState } from 'react'
import { ChevronDown } from 'lucide-react'
import { Link, useLocation } from 'react-router-dom'

import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle
} from '@renderer/components/ui/card'
import { Separator } from '@renderer/components/ui/separator'
import { getOpenMenuIds, menuTree } from '@renderer/student/menu'
import { cn } from '@renderer/lib/utils'
import type { MenuItem } from '@renderer/types/app'

export function AppSidebar(): React.JSX.Element {
  const { pathname } = useLocation()
  const [openIds, setOpenIds] = useState<Set<string>>(() => new Set(getOpenMenuIds(pathname)))
  const visibleOpenIds = useMemo(
    () => new Set([...openIds, ...getOpenMenuIds(pathname)]),
    [openIds, pathname]
  )

  function toggleMenu(id: string): void {
    setOpenIds((currentIds) => {
      const nextIds = new Set(currentIds)

      if (nextIds.has(id)) {
        nextIds.delete(id)
      } else {
        nextIds.add(id)
      }

      return nextIds
    })
  }

  return (
    <aside className="flex min-h-0 flex-col border-r bg-card">
      <div className="flex items-center gap-3 px-5 py-5">
        <div className="grid size-10 place-items-center rounded-lg bg-primary text-base font-bold text-primary-foreground">
          成
        </div>
        <div className="min-w-0 max-[760px]:hidden">
          <h1 className="truncate text-base font-semibold">成长报告助手</h1>
          <p className="text-xs text-muted-foreground">尚城幼儿园</p>
        </div>
      </div>

      <Separator />

      <div className="px-3 py-4">
        <p className="mb-2 px-3 text-xs font-medium text-muted-foreground max-[760px]:sr-only">
          导航
        </p>
        <nav className="flex h-auto w-full flex-col items-stretch justify-start gap-1 bg-transparent p-0">
          {menuTree.map((item) => (
            <MenuNode
              key={item.id}
              item={item}
              level={0}
              openIds={visibleOpenIds}
              onToggle={toggleMenu}
            />
          ))}
        </nav>
      </div>

      <div className="mt-auto p-4 max-[760px]:hidden">
        <Card className="shadow-none">
          <CardHeader className="p-4">
            <CardDescription>当前学期</CardDescription>
            <CardTitle className="text-base">2026 春季</CardTitle>
          </CardHeader>
          <CardContent className="px-4 pb-4 text-sm text-muted-foreground">
            共 20 份报告待处理
          </CardContent>
        </Card>
      </div>
    </aside>
  )
}

function MenuNode({
  item,
  level,
  openIds,
  onToggle
}: {
  item: MenuItem
  level: number
  openIds: Set<string>
  onToggle: (id: string) => void
}): React.JSX.Element {
  const Icon = item.icon
  const hasChildren = Boolean(item.children?.length)
  const isOpen = openIds.has(item.id)
  const paddingLeft = level === 0 ? undefined : `${level * 0.875 + 0.75}rem`
  const { pathname } = useLocation()
  const isActive = Boolean(item.path && item.path === pathname)
  const sharedClassName =
    'inline-flex h-10 w-full items-center justify-start gap-2 rounded-md px-3 text-sm font-medium transition-colors hover:bg-muted max-[760px]:justify-center max-[760px]:px-0'

  return (
    <div className="space-y-1">
      {item.path && !hasChildren ? (
        <Link
          to={item.path}
          className={cn(sharedClassName, isActive && 'bg-muted text-primary')}
          style={{ paddingLeft }}
          title={item.title}
        >
          {Icon && <Icon className="size-4" />}
          <span className="min-w-0 flex-1 truncate text-left max-[760px]:sr-only">
            {item.title}
          </span>
        </Link>
      ) : (
        <button
          type="button"
          className={cn(sharedClassName, isOpen && level === 0 && 'bg-muted/70')}
          style={{ paddingLeft }}
          title={item.title}
          onClick={() => onToggle(item.id)}
        >
          {Icon && <Icon className="size-4" />}
          <span className="min-w-0 flex-1 truncate text-left max-[760px]:sr-only">
            {item.title}
          </span>
          {hasChildren && (
            <ChevronDown
              className={cn(
                'size-4 text-muted-foreground transition-transform max-[760px]:hidden',
                isOpen && 'rotate-180'
              )}
            />
          )}
        </button>
      )}

      {hasChildren && isOpen && (
        <div className="space-y-1 max-[760px]:hidden">
          {item.children?.map((child) => (
            <MenuNode
              key={child.id}
              item={child}
              level={level + 1}
              openIds={openIds}
              onToggle={onToggle}
            />
          ))}
        </div>
      )}
    </div>
  )
}
