import { forwardRef, useState, useCallback, useEffect } from 'react'
import type { HTMLAttributes } from 'react'
import { createPortal } from 'react-dom'
import { cn } from '@/lib/utils'
import type { ReactNode } from 'react'
import { CloseLine, CloseLargeLine } from '../basic/icons-inline'
import { IconButton } from '../basic/icon-button'

const SIZE_CLASS = {
  sm: 'w-12 h-12',
  md: 'w-16 h-16',
  lg: 'w-20 h-20',
} as const

const PREVIEW_MAX = 'max-w-[90vw] max-h-[90vh] object-contain'
const closeClass = 'h-2.5 w-2.5 text-text-secondary'
const closeLargeClass = 'h-4 w-4 text-text-secondary'

export interface ImageAttachmentProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
  src: string
  alt?: string
  onRemove?: (e: React.MouseEvent) => void
  previewable?: boolean
  onClick?: (e: React.MouseEvent) => void
  size?: keyof typeof SIZE_CLASS
  closeIcon?: ReactNode
  closeLargeIcon?: ReactNode
}

export const ImageAttachment = forwardRef<HTMLDivElement, ImageAttachmentProps>(
  (
    {
      src,
      alt = '',
      onRemove,
      previewable = true,
      onClick,
      size = 'sm',
      className,
      closeIcon,
      closeLargeIcon,
      ...props
    },
    ref
  ) => {
    const [previewOpen, setPreviewOpen] = useState(false)
    const defaultClose = closeIcon ?? <CloseLine className={closeClass} />
    const defaultCloseLarge = closeLargeIcon ?? <CloseLargeLine className={closeLargeClass} />
    const showClose = typeof onRemove === 'function'

    const openPreview = useCallback(() => {
      if (previewable) setPreviewOpen(true)
    }, [previewable])

    const closePreview = useCallback(() => setPreviewOpen(false), [])

    const handleThumbClick = useCallback(
      (e: React.MouseEvent) => {
        onClick?.(e)
        if (!e.defaultPrevented && previewable) openPreview()
      },
      [onClick, previewable, openPreview]
    )

    const handleRemove = useCallback(
      (e: React.MouseEvent) => {
        e.stopPropagation()
        onRemove?.(e)
      },
      [onRemove]
    )

    useEffect(() => {
      if (!previewOpen) return
      const onKeyDown = (e: KeyboardEvent) => {
        if (e.key === 'Escape') closePreview()
      }
      window.addEventListener('keydown', onKeyDown)
      return () => window.removeEventListener('keydown', onKeyDown)
    }, [previewOpen, closePreview])

    const previewPortal =
      previewOpen && typeof document !== 'undefined'
        ? createPortal(
            <div
              className="fixed inset-0 z-[9999] flex items-center justify-center bg-bg-mask"
              role="dialog"
              aria-modal="true"
              aria-label="图片预览"
              onClick={(e) => {
                if (e.target === e.currentTarget) closePreview()
              }}
              onKeyDown={(e) => e.key === 'Escape' && closePreview()}
            >
              <img
                src={src}
                alt={alt}
                className={cn('rounded-lg shadow-xl', PREVIEW_MAX)}
                onClick={(e) => e.stopPropagation()}
                draggable={false}
              />
              <IconButton
                variant="tertiary"
                size="md"
                rounded="pill"
                icon={defaultCloseLarge}
                onClick={closePreview}
                aria-label="关闭预览"
                className="absolute top-4 right-4 bg-bg-base border border-border-tertiary shadow-sm"
              />
            </div>,
            document.body
          )
        : null

    return (
      <>
        <div
          ref={ref}
          role={previewable ? 'button' : undefined}
          tabIndex={previewable ? 0 : undefined}
          className={cn(
            'relative group shrink-0',
            previewable && 'cursor-pointer',
            className
          )}
          onClick={handleThumbClick}
          onKeyDown={
            previewable
              ? (e) => {
                  if (e.key === 'Enter' || e.key === ' ') {
                    e.preventDefault()
                    openPreview()
                  }
                }
              : undefined
          }
          {...props}
        >
          <img
            src={src}
            alt={alt}
            className={cn(
              'rounded-lg object-cover border border-border-tertiary',
              SIZE_CLASS[size]
            )}
            draggable={false}
          />
          {showClose && (
            <button
              type="button"
              onClick={handleRemove}
              aria-label="移除"
              className="absolute -top-0.5 -right-0.5 flex h-4 w-4 cursor-pointer items-center justify-center rounded-full bg-bg-base border border-border-tertiary shadow-sm opacity-0 group-hover:opacity-100 transition-opacity hover:bg-fill-secondary"
            >
              {defaultClose}
            </button>
          )}
        </div>
        {previewPortal}
      </>
    )
  }
)

ImageAttachment.displayName = 'ImageAttachment'
