import { useVirtualizer } from '@tanstack/react-virtual'
import * as icons from 'lucide-react'
import { Search, X } from 'lucide-react'
import { useState } from 'react'
import { Button } from '@/components/ui/button'
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@/components/ui/dialog'
import { Input } from '@/components/ui/input'
import { cn } from '@/lib/utils'

const allIcons = icons as unknown as Record<string, React.ComponentType<{ className?: string }>>

const ALL_ICON_NAMES: string[] = Object.keys(icons)
  .filter((key) => /^[A-Z]/.test(key) && !key.endsWith('Icon'))
  .sort()

const COLUMNS = 8
const ROW_HEIGHT = 40

interface IconPickerDialogProps {
  value: string | null
  onChange: (iconName: string | null) => void
}

export const IconPickerDialog = ({ value, onChange }: IconPickerDialogProps) => {
  const [open, setOpen] = useState(false)
  const [filter, setFilter] = useState('')
  const [scrollElement, setScrollElement] = useState<HTMLDivElement | null>(null)

  const filteredIcons = filter
    ? ALL_ICON_NAMES.filter((name) => name.toLowerCase().includes(filter.toLowerCase()))
    : ALL_ICON_NAMES

  const rowCount = Math.ceil(filteredIcons.length / COLUMNS)

  const virtualizer = useVirtualizer({
    count: rowCount,
    getScrollElement: () => scrollElement,
    estimateSize: () => ROW_HEIGHT,
    overscan: 5,
  })

  const CurrentIcon = (value && allIcons[value]) || null

  return (
    <Dialog
      open={open}
      onOpenChange={(isOpen) => {
        setOpen(isOpen)
        if (!isOpen) setFilter('')
      }}
    >
      <DialogTrigger render={<Button type="button" variant="outline" className="w-full justify-start gap-2" />}>
        {CurrentIcon ? <CurrentIcon className="size-4" /> : <Search className="size-4 text-muted-foreground" />}
        <span className={cn('truncate', !value && 'text-muted-foreground')}>{value ?? '选择图标'}</span>
      </DialogTrigger>

      <DialogContent className="max-w-lg">
        <DialogHeader>
          <DialogTitle>选择图标</DialogTitle>
          <DialogDescription>搜索并选择一个图标 · 共 {ALL_ICON_NAMES.length} 个可用图标</DialogDescription>
        </DialogHeader>

        <div className="flex gap-2">
          <Input
            value={filter}
            onChange={(e) => {
              setFilter(e.target.value)
              scrollElement?.scrollTo({ top: 0 })
            }}
            placeholder="搜索图标..."
            className="flex-1"
          />
          {value && (
            <Button
              type="button"
              variant="outline"
              size="icon"
              title="清除图标"
              onClick={() => {
                onChange(null)
                setOpen(false)
              }}
            >
              <X className="size-4" />
            </Button>
          )}
        </div>

        <div ref={setScrollElement} className="max-h-80 overflow-y-auto rounded-lg border p-2">
          <div
            style={{
              height: virtualizer.getTotalSize(),
              width: '100%',
              position: 'relative',
            }}
          >
            {virtualizer.getVirtualItems().map((virtualRow) => {
              const startIndex = virtualRow.index * COLUMNS
              const rowIcons = filteredIcons.slice(startIndex, startIndex + COLUMNS)

              return (
                <div
                  key={virtualRow.key}
                  className="grid grid-cols-8 gap-1"
                  style={{
                    position: 'absolute',
                    top: 0,
                    left: 0,
                    width: '100%',
                    height: ROW_HEIGHT,
                    transform: `translateY(${virtualRow.start}px)`,
                  }}
                >
                  {rowIcons.map((name) => {
                    const Icon = allIcons[name]
                    if (!Icon) return null

                    return (
                      <Button
                        key={name}
                        type="button"
                        size="icon"
                        variant={value === name ? 'secondary' : 'ghost'}
                        title={name}
                        onClick={() => {
                          onChange(name)
                          setOpen(false)
                        }}
                      >
                        <Icon className="size-4" />
                      </Button>
                    )
                  })}
                </div>
              )
            })}
          </div>
        </div>

        {filteredIcons.length === 0 && <p className="text-center text-sm text-muted-foreground">未找到匹配图标</p>}
      </DialogContent>
    </Dialog>
  )
}
