import { Image as ImageIcon, Search, X } from 'lucide-react'
import { useEffect, useMemo, useState } from 'react'
import { toast } from 'sonner'

import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Select } from '@/components/ui/select'
import { Skeleton } from '@/components/ui/skeleton'
import { adminApi, ApiError } from '@/lib/api'
import type { AdminMediaObjectResponse } from '@/lib/types'

type MediaLibraryPickerDialogProps = {
  open: boolean
  selectedUrl?: string
  preferredPrefix?: string
  onClose: () => void
  onSelect: (item: AdminMediaObjectResponse) => void
}

const DEFAULT_PREFIX_OPTIONS = [
  'all',
  'post-covers/',
  'review-covers/',
  'category-covers/',
  'tag-covers/',
  'site-assets/',
  'seo-assets/',
  'music-covers/',
  'friend-link-avatars/',
  'uploads/',
] as const

function prefixLabel(value: string) {
  switch (value) {
    case 'all':
      return '全部目录'
    case 'post-covers/':
      return '文章封面'
    case 'review-covers/':
      return '评测封面'
    case 'category-covers/':
      return '分类封面'
    case 'tag-covers/':
      return '标签封面'
    case 'site-assets/':
      return '站点资源'
    case 'seo-assets/':
      return 'SEO 图片'
    case 'music-covers/':
      return '音乐封面'
    case 'friend-link-avatars/':
      return '友链头像'
    case 'uploads/':
      return '通用上传'
    default:
      return value
  }
}

function isLikelyImage(item: AdminMediaObjectResponse) {
  return /\.(png|jpe?g|webp|avif|gif|svg)$/i.test(item.key)
}

export function MediaLibraryPickerDialog({
  open,
  selectedUrl,
  preferredPrefix,
  onClose,
  onSelect,
}: MediaLibraryPickerDialogProps) {
  const [items, setItems] = useState<AdminMediaObjectResponse[]>([])
  const [loading, setLoading] = useState(false)
  const [prefixFilter, setPrefixFilter] = useState(preferredPrefix ?? 'all')
  const [searchTerm, setSearchTerm] = useState('')

  const prefixOptions = useMemo(
    () => Array.from(new Set([preferredPrefix, ...DEFAULT_PREFIX_OPTIONS].filter(Boolean))) as string[],
    [preferredPrefix],
  )

  useEffect(() => {
    if (!open) {
      return
    }

    setPrefixFilter(preferredPrefix ?? 'all')
    setSearchTerm('')
  }, [open, preferredPrefix])

  useEffect(() => {
    if (!open) {
      return
    }

    let cancelled = false

    async function loadItems() {
      try {
        setLoading(true)
        const result = await adminApi.listMediaObjects({
          prefix: prefixFilter === 'all' ? undefined : prefixFilter,
          limit: 200,
        })

        if (!cancelled) {
          setItems(result.items)
        }
      } catch (error) {
        if (!cancelled) {
          toast.error(error instanceof ApiError ? error.message : '加载媒体库失败。')
        }
      } finally {
        if (!cancelled) {
          setLoading(false)
        }
      }
    }

    void loadItems()

    return () => {
      cancelled = true
    }
  }, [open, prefixFilter])

  useEffect(() => {
    if (!open) {
      return
    }

    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        onClose()
      }
    }

    document.addEventListener('keydown', handleKeyDown)
    return () => document.removeEventListener('keydown', handleKeyDown)
  }, [open, onClose])

  const filteredItems = useMemo(() => {
    const keyword = searchTerm.trim().toLowerCase()
    if (!keyword) {
      return items
    }

    return items.filter((item) =>
      [
        item.key,
        item.title ?? '',
        item.alt_text ?? '',
        item.caption ?? '',
        ...(item.tags ?? []),
      ]
        .join('\n')
        .toLowerCase()
        .includes(keyword),
    )
  }, [items, searchTerm])

  if (!open) {
    return null
  }

  return (
    <div
      className="fixed inset-0 z-[70] bg-slate-950/70 px-4 py-5 backdrop-blur-sm xl:px-8 xl:py-8"
      onClick={(event) => {
        if (event.target === event.currentTarget) {
          onClose()
        }
      }}
    >
      <div className="mx-auto flex h-full w-full max-w-7xl flex-col overflow-hidden rounded-[32px] border border-border/70 bg-background shadow-[0_40px_120px_rgba(15,23,42,0.45)]">
        <div className="flex flex-col gap-4 border-b border-border/70 bg-background/95 px-6 py-5 xl:flex-row xl:items-start xl:justify-between">
          <div className="space-y-3">
            <Badge variant="secondary">媒体库选择器</Badge>
            <div>
              <h3 className="text-2xl font-semibold tracking-tight">从已有媒体库选择图片</h3>
              <p className="mt-2 max-w-3xl text-sm leading-7 text-muted-foreground">
                可按目录和关键字筛选；点击“使用这张”后会把媒体库 URL 回填到当前表单。
              </p>
            </div>
          </div>

          <Button variant="ghost" onClick={onClose}>
            <X className="h-4 w-4" />
            关闭
          </Button>
        </div>

        <div className="grid gap-4 border-b border-border/70 bg-background/80 px-6 py-4 lg:grid-cols-[220px_minmax(0,1fr)]">
          <Select value={prefixFilter} onChange={(event) => setPrefixFilter(event.target.value)}>
            {prefixOptions.map((option) => (
              <option key={option} value={option}>
                {prefixLabel(option)}
              </option>
            ))}
          </Select>
          <div className="relative">
            <Search className="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
            <Input
              className="pl-10"
              value={searchTerm}
              onChange={(event) => setSearchTerm(event.target.value)}
              placeholder="按 key / 标题 / alt / 标签搜索"
            />
          </div>
        </div>

        <div className="min-h-0 flex-1 overflow-y-auto px-6 py-5">
          {loading ? (
            <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
              {Array.from({ length: 6 }).map((_, index) => (
                <Skeleton key={index} className="h-[260px] rounded-[28px]" />
              ))}
            </div>
          ) : filteredItems.length ? (
            <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
              {filteredItems.map((item) => {
                const isSelected = selectedUrl === item.url

                return (
                  <div
                    key={item.key}
                    className={`overflow-hidden rounded-[28px] border bg-background/75 ${
                      isSelected
                        ? 'border-primary/40 shadow-[0_16px_44px_rgba(37,99,235,0.16)]'
                        : 'border-border/70'
                    }`}
                  >
                    <div className="aspect-[16/9] overflow-hidden border-b border-border/70 bg-muted/30">
                      {isLikelyImage(item) ? (
                        <img
                          src={item.url}
                          alt={item.alt_text ?? item.title ?? item.key}
                          className="h-full w-full object-cover"
                        />
                      ) : (
                        <div className="flex h-full items-center justify-center text-muted-foreground">
                          <ImageIcon className="h-8 w-8" />
                        </div>
                      )}
                    </div>

                    <div className="space-y-3 p-4">
                      <div className="space-y-2">
                        <p className="line-clamp-1 text-sm font-medium">{item.title || item.key}</p>
                        <p className="line-clamp-2 break-all text-xs text-muted-foreground">{item.key}</p>
                        {item.tags.length ? (
                          <div className="flex flex-wrap gap-2">
                            {item.tags.slice(0, 3).map((tag) => (
                              <Badge key={`${item.key}-${tag}`} variant="outline">
                                {tag}
                              </Badge>
                            ))}
                          </div>
                        ) : null}
                      </div>

                      <div className="flex items-center justify-between gap-3">
                        <span className="text-xs text-muted-foreground">
                          {prefixLabel(item.key.split('/')[0] ? `${item.key.split('/')[0]}/` : 'uploads/')}
                        </span>
                        <Button
                          size="sm"
                          onClick={() => {
                            onSelect(item)
                            onClose()
                          }}
                        >
                          使用这张
                        </Button>
                      </div>
                    </div>
                  </div>
                )
              })}
            </div>
          ) : (
            <div className="flex h-full min-h-[240px] flex-col items-center justify-center gap-3 rounded-[28px] border border-dashed border-border/70 bg-background/40 text-center text-muted-foreground">
              <ImageIcon className="h-8 w-8" />
              <p>当前筛选条件下没有可选媒体。</p>
            </div>
          )}
        </div>
      </div>
    </div>
  )
}
