import { memo, useState, useCallback, useEffect } from 'react'
import type { ReactNode } from 'react'
import { cn } from '@/lib/utils'
import { motion, AnimatePresence } from 'framer-motion'
import { Tooltip } from '../basic/tooltip'
import { IconButton } from '../basic/icon-button'
import { ArrowUpLine, CloseLine, ArrowDownSLine } from '../basic/icons-inline'
import { Scrollbar } from '../basic/scrollbar'

export interface QueueIndicatorItem {
  id: string
  label: ReactNode
  attachmentCount?: number
}

export interface QueueIndicatorLabels {
  title?: string
  sendNowTip?: string
  removeTip?: string
  fileLabel?: string
  filesLabel?: string
}

const DEFAULT_LABELS: Required<QueueIndicatorLabels> = {
  title: 'In queue',
  sendNowTip: 'Send now',
  removeTip: 'Remove',
  fileLabel: 'file',
  filesLabel: 'files',
}

export interface QueueIndicatorProps {
  items: QueueIndicatorItem[]
  onRemoveItem?: (itemId: string) => void
  onSendNow?: (itemId: string) => void
  isStreaming?: boolean
  hasStatusCardBelow?: boolean
  labels?: QueueIndicatorLabels
  defaultExpanded?: boolean
  storageKey?: string
  arrowUpIcon?: ReactNode
  closeIcon?: ReactNode
  arrowDownSIcon?: ReactNode
}

const arrowUpClass = 'w-3.5 h-3.5'
const closeClass = 'w-3.5 h-3.5'
const arrowDownClass = 'w-4 h-4 text-text-tertiary transition-transform duration-200'

const QueueItemRow = memo(function QueueItemRow({
  item,
  onRemove,
  onSendNow,
  labels,
  arrowUpIcon,
  closeIcon,
}: {
  item: QueueIndicatorItem
  onRemove?: (itemId: string) => void
  onSendNow?: (itemId: string) => void
  labels: Required<QueueIndicatorLabels>
  arrowUpIcon: ReactNode
  closeIcon: ReactNode
}) {
  const handleRemove = useCallback(
    (e: React.MouseEvent) => {
      e.stopPropagation()
      onRemove?.(item.id)
    },
    [item.id, onRemove]
  )

  const handleSendNow = useCallback(
    (e: React.MouseEvent) => {
      e.stopPropagation()
      onSendNow?.(item.id)
    },
    [item.id, onSendNow]
  )

  const attachmentCount = item.attachmentCount ?? 0
  const fileWord = attachmentCount === 1 ? labels.fileLabel : labels.filesLabel

  return (
    <div className="flex items-center gap-2 px-3 py-1.5 text-xs leading-xs hover:bg-fill-tertiary transition-colors cursor-default">
      <span className="truncate flex-1 text-text">{item.label}</span>
      {attachmentCount > 0 && (
        <span className="shrink-0 text-xs leading-xs text-text-tertiary">
          +{attachmentCount} {fileWord}
        </span>
      )}
      <div className="flex items-center gap-0.5">
        {onSendNow && (
          <Tooltip content={labels.sendNowTip} side="top">
            <IconButton
              size="sm"
              variant="ghost"
              icon={arrowUpIcon}
              aria-label={labels.sendNowTip}
              className="shrink-0"
              onClick={handleSendNow}
            />
          </Tooltip>
        )}
        {onRemove && (
          <Tooltip content={labels.removeTip} side="top">
            <IconButton
              size="sm"
              variant="ghost"
              icon={closeIcon}
              aria-label={labels.removeTip}
              className="shrink-0"
              onClick={handleRemove}
            />
          </Tooltip>
        )}
      </div>
    </div>
  )
})

export const QueueIndicator = memo(function QueueIndicator({
  items,
  onRemoveItem,
  onSendNow,
  isStreaming = false,
  hasStatusCardBelow = false,
  labels: labelsProp,
  defaultExpanded = true,
  storageKey,
  arrowUpIcon,
  closeIcon,
  arrowDownSIcon,
}: QueueIndicatorProps) {
  void isStreaming
  const labels = { ...DEFAULT_LABELS, ...labelsProp }

  const defaultArrowUp = arrowUpIcon ?? <ArrowUpLine className={arrowUpClass} />
  const defaultClose = closeIcon ?? <CloseLine className={closeClass} />
  const defaultArrowDown =
    arrowDownSIcon ?? <ArrowDownSLine className={arrowDownClass} />

  const [isExpanded, setIsExpanded] = useState(() => {
    if (typeof window === 'undefined') return defaultExpanded
    if (storageKey) {
      const saved = localStorage.getItem(storageKey)
      return saved !== null ? saved === 'true' : defaultExpanded
    }
    return defaultExpanded
  })

  useEffect(() => {
    if (storageKey) {
      localStorage.setItem(storageKey, String(isExpanded))
    }
  }, [storageKey, isExpanded])

  if (items.length === 0) return null

  const containerStyles = cn(
    'w-full overflow-hidden flex flex-col',
    'border border-b-0 border-border border-border-tertiary bg-bg-base',
    !hasStatusCardBelow && 'rounded-t-xl'
  )

  return (
    <motion.div
      initial={{ opacity: 0, y: 8 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.2, ease: [0.16, 1, 0.3, 1] }}
      className={containerStyles}
    >
      <div
        role="button"
        tabIndex={0}
        onClick={() => setIsExpanded(!isExpanded)}
        onKeyDown={(e) => {
          if (e.key === 'Enter' || e.key === ' ') {
            e.preventDefault()
            setIsExpanded(!isExpanded)
          }
        }}
        aria-expanded={isExpanded}
        aria-label={`${isExpanded ? 'Collapse' : 'Expand'} queue`}
        className="flex items-center justify-between px-3 py-1 h-7 cursor-pointer bg-fill-tertiary hover:bg-fill-secondary transition-colors duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary-border"
      >
        <div className="flex items-center gap-2 flex-1 min-w-0">
          <span
            className={cn(
              'inline-flex items-center justify-center',
              !isExpanded && '-rotate-90'
            )}
          >
            {defaultArrowDown}
          </span>
          <span className="text-xs leading-xs font-medium text-text-secondary">
            {labels.title}
          </span>
        </div>
      </div>

      <AnimatePresence initial={false}>
        {isExpanded && (
          <motion.div
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: 'auto', opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            transition={{ duration: 0.2, ease: [0.23, 1, 0.32, 1] }}
            className="overflow-hidden"
          >
            <Scrollbar
              scrollbarVisibility="auto"
              maxHeight={208}
              className="border-t border-border-tertiary scroll-smooth"
            >
              {items.map((item) => (
                <QueueItemRow
                  key={item.id}
                  item={item}
                  onRemove={onRemoveItem}
                  onSendNow={onSendNow}
                  labels={labels}
                  arrowUpIcon={defaultArrowUp}
                  closeIcon={defaultClose}
                />
              ))}
            </Scrollbar>
          </motion.div>
        )}
      </AnimatePresence>
    </motion.div>
  )
})

QueueIndicator.displayName = 'QueueIndicator'
