'use client'

import { useId, useState, useRef } from 'react'
import * as Dialog from '@radix-ui/react-dialog'
import { X, Upload, Search, ImageIcon, Loader2 } from 'lucide-react'
import { toast } from 'sonner'
import { cmsApi } from '../lib/api.js'
import { adminPortalContainer } from '../lib/portal-container.js'
import { useApiData } from '../lib/useApiData.js'

interface MediaItem {
  id: string
  filename: string
  storageKey: string
  /** Normalized public URL from the media list endpoint (preferred for display). */
  url?: string
  /** Curated alt text from the media library (normalized as `altTag`). */
  altTag?: string
  mimeType: string
  fileSize: number
  width?: number
  height?: number
}

/** Minimal selected-asset shape exposed to callers that need the asset id. */
export interface SelectedMediaItem {
  id: string
  storageKey: string
  /** Normalized public URL (falls back to storageKey when absent). */
  url: string
  filename: string
  mimeType: string
  width?: number
  height?: number
}

export interface MediaPickerModalProps {
  open: boolean
  onClose: () => void
  onSelect: (url: string, alt?: string) => void
  /**
   * Optional richer callback fired alongside `onSelect` with the full media
   * item, so callers that need to store the asset id (not just the URL) can.
   */
  onSelectItem?: (item: SelectedMediaItem) => void
  accept?: string
  /**
   * Hide the "Upload New" tab and show only the existing library. Used where a
   * caller has its own upload path (e.g. brand assets, which upload with
   * format-preserving options) but still wants to reuse library assets.
   */
  libraryOnly?: boolean
}

export function MediaPickerModal({
  open,
  onClose,
  onSelect,
  onSelectItem,
  accept,
  libraryOnly = false,
}: MediaPickerModalProps) {
  const [tab, setTab] = useState<'library' | 'upload'>('library')
  const [search, setSearch] = useState('')
  const [uploading, setUploading] = useState(false)
  const fileInputRef = useRef<HTMLInputElement>(null)
  const searchId = useId()

  const { data, loading, refetch } = useApiData<{ data: { items: MediaItem[] } }>(
    open ? `/media?pageSize=50${search ? `&search=${encodeURIComponent(search)}` : ''}` : null,
  )

  const items = (data as any)?.data?.items ?? (data as any)?.items ?? []
  const imageItems = items.filter((item: MediaItem) => item.mimeType.startsWith('image/'))

  async function handleUpload(files: FileList | null) {
    if (!files || files.length === 0) return
    setUploading(true)

    const file = files[0]!
    const formData = new FormData()
    formData.append('file', file)

    const res = await cmsApi<MediaItem>('/media/upload', {
      method: 'POST',
      body: formData,
    })

    if (res.error) {
      toast.error(res.error)
    } else if (res.data) {
      const mediaItem = res.data as MediaItem
      const url = mediaItem.url || mediaItem.storageKey || ''
      toast.success(`Uploaded ${file.name}`)
      onSelectItem?.({
        id: mediaItem.id,
        storageKey: mediaItem.storageKey,
        url,
        filename: mediaItem.filename ?? file.name,
        mimeType: mediaItem.mimeType ?? file.type,
        width: mediaItem.width,
        height: mediaItem.height,
      })
      onSelect(url, file.name)
      onClose()
    }

    setUploading(false)
    if (fileInputRef.current) fileInputRef.current.value = ''
  }

  function handleSelectItem(item: MediaItem) {
    const url = item.url || item.storageKey || ''
    onSelectItem?.({
      id: item.id,
      storageKey: item.storageKey,
      url,
      filename: item.filename,
      mimeType: item.mimeType,
      width: item.width,
      height: item.height,
    })
    // Prefer the asset's curated alt text from the library so inserted images
    // carry meaningful alt instead of a filename. Callers can still override.
    onSelect(url, item.altTag?.trim() || item.filename)
    onClose()
  }

  return (
    <Dialog.Root open={open} onOpenChange={(next) => !next && onClose()}>
      <Dialog.Portal container={adminPortalContainer()}>
        <Dialog.Overlay className="fixed inset-0 z-50 bg-black/40" />
        <Dialog.Content
          aria-describedby={undefined}
          className="bg-card text-card-foreground border-border fixed top-1/2 left-1/2 z-50 mx-4 flex max-h-[80vh] w-[calc(100%-2rem)] max-w-2xl -translate-x-1/2 -translate-y-1/2 flex-col rounded-xl border shadow-2xl focus:outline-none"
        >
          <div className="border-border flex items-center justify-between border-b px-4 py-3">
            <Dialog.Title className="text-foreground text-lg font-medium">
              Insert Image
            </Dialog.Title>
            <Dialog.Close asChild>
              <button
                type="button"
                aria-label="Close media picker"
                className="text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:ring-ring rounded-lg p-1.5 transition-colors focus-visible:ring-2 focus-visible:outline-none"
              >
                <X className="h-5 w-5" aria-hidden />
              </button>
            </Dialog.Close>
          </div>

          {!libraryOnly && (
            <div className="border-border flex border-b" role="tablist" aria-label="Image source">
              <button
                type="button"
                role="tab"
                aria-selected={tab === 'library'}
                onClick={() => setTab('library')}
                className={`flex-1 px-4 py-2.5 text-sm font-medium transition-colors ${
                  tab === 'library'
                    ? 'border-primary text-primary border-b-2'
                    : 'text-muted-foreground hover:text-foreground'
                }`}
              >
                Media Library
              </button>
              <button
                type="button"
                role="tab"
                aria-selected={tab === 'upload'}
                onClick={() => setTab('upload')}
                className={`flex-1 px-4 py-2.5 text-sm font-medium transition-colors ${
                  tab === 'upload'
                    ? 'border-primary text-primary border-b-2'
                    : 'text-muted-foreground hover:text-foreground'
                }`}
              >
                Upload New
              </button>
            </div>
          )}

          <div className="flex-1 overflow-y-auto p-4">
            {libraryOnly || tab === 'library' ? (
              <>
                <div className="relative mb-4">
                  <Search
                    className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2"
                    aria-hidden
                  />
                  <input
                    id={searchId}
                    type="text"
                    value={search}
                    onChange={(e) => setSearch(e.target.value)}
                    placeholder="Search images..."
                    aria-label="Search images"
                    className="border-input bg-background text-foreground focus:ring-ring w-full rounded-lg border py-2 pr-3 pl-9 text-sm focus:ring-2 focus:outline-none"
                  />
                </div>

                {loading ? (
                  <div className="flex items-center justify-center py-12">
                    <Loader2 className="text-muted-foreground h-6 w-6 animate-spin" aria-hidden />
                  </div>
                ) : imageItems.length === 0 ? (
                  <div className="text-muted-foreground py-12 text-center text-sm">
                    No images found. Try uploading one.
                  </div>
                ) : (
                  <div className="grid grid-cols-3 gap-3 sm:grid-cols-4">
                    {imageItems.map((item: MediaItem) => {
                      const src = item.url || item.storageKey
                      return (
                        <button
                          key={item.id}
                          type="button"
                          onClick={() => handleSelectItem(item)}
                          title={item.filename}
                          className="group border-border bg-muted hover:border-primary relative aspect-square overflow-hidden rounded-lg border-2 transition-colors"
                        >
                          {src ? (
                            <img
                              src={src}
                              alt={item.filename}
                              loading="lazy"
                              className="h-full w-full object-contain"
                            />
                          ) : (
                            <div className="flex h-full w-full items-center justify-center">
                              <ImageIcon className="text-muted-foreground h-8 w-8" aria-hidden />
                            </div>
                          )}
                          <div className="absolute inset-x-0 bottom-0 bg-black/60 p-1.5 opacity-0 transition-opacity group-hover:opacity-100">
                            <p className="truncate text-xs text-white">{item.filename}</p>
                          </div>
                        </button>
                      )
                    })}
                  </div>
                )}
              </>
            ) : (
              <div className="flex flex-col items-center justify-center py-12">
                <input
                  ref={fileInputRef}
                  type="file"
                  accept={accept ?? 'image/*'}
                  className="hidden"
                  onChange={(e) => handleUpload(e.target.files)}
                />
                <div className="bg-primary/10 mb-4 flex h-16 w-16 items-center justify-center rounded-full">
                  {uploading ? (
                    <Loader2 className="text-primary h-8 w-8 animate-spin" aria-hidden />
                  ) : (
                    <Upload className="text-primary h-8 w-8" aria-hidden />
                  )}
                </div>
                <p className="text-muted-foreground mb-4 text-sm">
                  {uploading ? 'Uploading...' : 'Select an image file to upload'}
                </p>
                {!uploading && (
                  <button
                    type="button"
                    onClick={() => fileInputRef.current?.click()}
                    className="bg-primary text-primary-foreground rounded-lg px-4 py-2 text-sm transition-opacity hover:opacity-90"
                  >
                    Choose File
                  </button>
                )}
              </div>
            )}
          </div>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  )
}
