import { CheckSquare, Download, Images, Square, Upload } from 'lucide-react'
import { useRef, useState } from 'react'
import { toast } from 'sonner'

import { MediaLibraryPickerDialog } from '@/components/media-library-picker-dialog'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Select } from '@/components/ui/select'
import { adminApi, ApiError } from '@/lib/api'
import {
  formatCompressionPreview,
  prepareImageForUpload,
  type MediaUploadTargetFormat,
} from '@/lib/image-compress'
import { cn } from '@/lib/utils'

type RemoteTargetFormat = 'original' | 'webp' | 'avif'

type MediaUrlControlsProps = {
  value: string
  onChange: (value: string) => void
  prefix: string
  contextLabel: string
  mode?: 'image' | 'cover'
  className?: string
  remoteTitle?: string | null
  accept?: string
  dataTestIdPrefix?: string
}

function formatLabelForUploadTarget(value: MediaUploadTargetFormat) {
  switch (value) {
    case 'avif':
      return 'AVIF'
    case 'webp':
      return 'WebP'
    default:
      return '自动'
  }
}

export function MediaUrlControls({
  value,
  onChange,
  prefix,
  contextLabel,
  mode = 'image',
  className,
  remoteTitle,
  accept = 'image/*',
  dataTestIdPrefix,
}: MediaUrlControlsProps) {
  const fileInputRef = useRef<HTMLInputElement>(null)
  const [uploading, setUploading] = useState(false)
  const [downloadingRemote, setDownloadingRemote] = useState(false)
  const [compressBeforeUpload, setCompressBeforeUpload] = useState(true)
  const [compressQuality, setCompressQuality] = useState('0.82')
  const [uploadTargetFormat, setUploadTargetFormat] = useState<MediaUploadTargetFormat>('avif')
  const [remoteUrl, setRemoteUrl] = useState('')
  const [remoteTargetFormat, setRemoteTargetFormat] = useState<RemoteTargetFormat>('original')
  const [pickerOpen, setPickerOpen] = useState(false)

  const quality = Number.parseFloat(compressQuality)
  const safeQuality = Number.isFinite(quality) ? Math.min(Math.max(quality, 0.4), 0.95) : 0.82

  return (
    <div className={cn('rounded-2xl border border-border/70 bg-background/55 p-4', className)}>
      <div className="space-y-3">
        <div className="flex flex-wrap items-center gap-3">
          <input
            ref={fileInputRef}
            className="hidden"
            type="file"
            accept={accept}
            onChange={async (event) => {
              const file = event.target.files?.item(0)
              event.currentTarget.value = ''
              if (!file) {
                return
              }

              try {
                setUploading(true)
                const prepared = await prepareImageForUpload(file, {
                  compress: compressBeforeUpload,
                  quality: safeQuality,
                  targetFormat: uploadTargetFormat,
                  contextLabel: `${contextLabel}（${file.name}）`,
                  mode,
                })

                if (prepared.preview) {
                  toast.message(formatCompressionPreview(prepared.preview))
                }

                const uploaded = await adminApi.uploadMediaObjects([prepared.file], { prefix })
                const url = uploaded.uploaded[0]?.url
                if (!url) {
                  throw new Error('上传完成但没有返回 URL')
                }

                if (compressBeforeUpload && uploadTargetFormat !== 'auto') {
                  const expectedMimeType =
                    uploadTargetFormat === 'avif' ? 'image/avif' : 'image/webp'
                  if (prepared.file.type !== expectedMimeType) {
                    toast.warning(
                      `当前环境无法直接导出 ${formatLabelForUploadTarget(uploadTargetFormat)}，已回退为 ${prepared.file.type || '原格式'}。`,
                    )
                  }
                }

                onChange(url)
                toast.success('已上传到媒体库，并回填 URL。')
              } catch (error) {
                toast.error(error instanceof ApiError ? error.message : '上传到媒体库失败。')
              } finally {
                setUploading(false)
              }
            }}
          />

          <Button
            type="button"
            variant="outline"
            disabled={uploading}
            data-testid={dataTestIdPrefix ? `${dataTestIdPrefix}-upload` : undefined}
            onClick={() => fileInputRef.current?.click()}
          >
            <Upload className="h-4 w-4" />
            {uploading ? '上传中...' : '上传到媒体库'}
          </Button>

          <Button
            type="button"
            variant="outline"
            data-testid={dataTestIdPrefix ? `${dataTestIdPrefix}-library` : undefined}
            onClick={() => setPickerOpen(true)}
          >
            <Images className="h-4 w-4" />
            从媒体库选
          </Button>

          <Button
            type="button"
            variant="outline"
            onClick={() => setCompressBeforeUpload((current) => !current)}
          >
            {compressBeforeUpload ? <CheckSquare className="h-4 w-4" /> : <Square className="h-4 w-4" />}
            压缩上传
          </Button>

          <Select
            value={uploadTargetFormat}
            onChange={(event) => setUploadTargetFormat(event.target.value as MediaUploadTargetFormat)}
            disabled={!compressBeforeUpload}
            className="min-w-[180px]"
          >
            <option value="avif">压缩为 AVIF</option>
            <option value="webp">压缩为 WebP</option>
            <option value="auto">自动选择格式</option>
          </Select>

          <Input
            className="w-[92px]"
            value={compressQuality}
            onChange={(event) => setCompressQuality(event.target.value)}
            placeholder="0.82"
            disabled={!compressBeforeUpload}
          />
        </div>

        <div className="space-y-3">
          <Input
            value={remoteUrl}
            onChange={(event) => setRemoteUrl(event.target.value)}
            placeholder="https://example.com/cover.webp"
            data-testid={dataTestIdPrefix ? `${dataTestIdPrefix}-remote-url` : undefined}
          />
          <div className="flex flex-wrap gap-3">
            <div className="min-w-[220px] flex-1">
              <Select
                value={remoteTargetFormat}
                onChange={(event) => setRemoteTargetFormat(event.target.value as RemoteTargetFormat)}
              >
                <option value="original">按原格式抓取</option>
                <option value="webp">抓取后转 WebP</option>
                <option value="avif">抓取后转 AVIF</option>
              </Select>
            </div>
            <Button
              type="button"
              variant="outline"
              className="shrink-0"
              disabled={!remoteUrl.trim() || downloadingRemote}
              data-testid={dataTestIdPrefix ? `${dataTestIdPrefix}-remote-download` : undefined}
              onClick={async () => {
                if (!remoteUrl.trim()) {
                  toast.error('请先填写远程图片 URL。')
                  return
                }

                try {
                  setDownloadingRemote(true)
                  const result = await adminApi.downloadMediaObject({
                    sourceUrl: remoteUrl.trim(),
                    prefix,
                    targetFormat: remoteTargetFormat,
                    title: remoteTitle?.trim() || null,
                    sync: true,
                  })

                  if (!result.url) {
                    throw new Error(result.job_id ? `远程抓取已入队：#${result.job_id}` : '远程抓取完成但未返回 URL')
                  }

                  onChange(result.url)
                  setRemoteUrl('')
                  toast.success('远程素材已写入媒体库，并回填 URL。')
                } catch (error) {
                  toast.error(
                    error instanceof ApiError
                      ? error.message
                      : error instanceof Error
                        ? error.message
                        : '远程抓取失败。',
                  )
                } finally {
                  setDownloadingRemote(false)
                }
              }}
            >
              <Download className="h-4 w-4" />
              {downloadingRemote ? '抓取中...' : '抓取到媒体库'}
            </Button>
          </div>
        </div>

        <p className="text-xs leading-5 text-muted-foreground">
          上传 / 抓取完成后会自动回填当前 URL；也可以直接在上面的输入框里手填外链。
          {value.trim() ? ' 当前已有值，可继续覆盖。' : ''}
        </p>
      </div>

      <MediaLibraryPickerDialog
        open={pickerOpen}
        selectedUrl={value}
        preferredPrefix={prefix}
        onClose={() => setPickerOpen(false)}
        onSelect={(item) => {
          onChange(item.url)
          toast.success('已从媒体库选中并回填 URL。')
        }}
      />
    </div>
  )
}
