"use client";

import * as React from "react";
import { toast } from "sonner";
import {
  Image as ImageIcon,
  Upload,
  Search,
  Trash2,
  ExternalLink,
  Copy,
  Info,
  CheckCircle2,
  AlertTriangle,
  FileText,
  ShieldCheck,
  RefreshCw,
  X,
  RotateCcw,
  CheckSquare,
  Square,
  ChevronDown,
  Sparkles,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { fetchWithAdminCache, invalidateAdminCache } from "@/lib/admin/client-cache";

interface MediaItem {
  id: string;
  filename: string;
  originalName: string;
  url: string;
  mimeType: string;
  size: number;
  width?: number | null;
  height?: number | null;
  alt: string;
  caption?: string | null;
  usedInPosts: string[];
  uploadedBy: string;
  uploadedAt: string;
  publicId?: string;
  folder?: string;
}

interface UploadQueueItem {
  id: string;
  batchId?: string;
  batchTotal?: number;
  fingerprint: string;
  file: File;
  name: string;
  size: number;
  thumbnailUrl: string;
  status: "QUEUED" | "UPLOADING" | "PROCESSING" | "COMPLETED" | "FAILED" | "CANCELLED";
  progress: number;
  error?: string;
  xhr?: XMLHttpRequest;
}

export default function AdminMediaPage() {
  const [items, setItems] = React.useState<MediaItem[]>([]);
  const [loading, setLoading] = React.useState(true);
  const [search, setSearch] = React.useState("");
  const [selectedItem, setSelectedItem] = React.useState<MediaItem | null>(null);
  const [referencingPosts, setReferencingPosts] = React.useState<string[]>([]);
  const [assetUsage, setAssetUsage] = React.useState<any>(null);
  const [replacing, setReplacing] = React.useState(false);

  // Multi-selection state
  const [selectedIds, setSelectedIds] = React.useState<Set<string>>(new Set());

  // Upload Queue state
  const [uploadQueue, setUploadQueue] = React.useState<UploadQueueItem[]>([]);
  const [isQueueOpen, setIsQueueOpen] = React.useState(false);
  const [isDragging, setIsDragging] = React.useState(false);

  // Single Deletion modal state
  const [itemToDelete, setItemToDelete] = React.useState<MediaItem | null>(null);
  const [deleteWarningPosts, setDeleteWarningPosts] = React.useState<string[]>([]);
  const [deleting, setDeleting] = React.useState(false);

  // Bulk Deletion modal state
  const [showBulkDeleteModal, setShowBulkDeleteModal] = React.useState(false);
  const [bulkDeletePreflight, setBulkDeletePreflight] = React.useState<{
    checking: boolean;
    safeCount: number;
    inUseCount: number;
    inUseDetails: { id: string; filename: string; reason: string }[];
  }>({
    checking: false,
    safeCount: 0,
    inUseCount: 0,
    inUseDetails: [],
  });
  const [bulkDeleting, setBulkDeleting] = React.useState(false);

  // Edit metadata in drawer
  const [editAlt, setEditAlt] = React.useState("");
  const [editCaption, setEditCaption] = React.useState("");
  const [savingMeta, setSavingMeta] = React.useState(false);

  const fileInputRef = React.useRef<HTMLInputElement>(null);

  const fetchMedia = React.useCallback(async (forceFresh = false) => {
    try {
      setLoading(true);
      const params = new URLSearchParams();
      if (search.trim()) params.set("search", search.trim());
      const data = await fetchWithAdminCache<{ items?: MediaItem[] }>(
        `/api/admin/media?${params.toString()}`,
        { tags: ["media"], forceFresh }
      );
      setItems(data.items || []);
    } catch (err: any) {
      toast.error(err.message || "Failed to load media assets");
    } finally {
      setLoading(false);
    }
  }, [search]);

  React.useEffect(() => {
    fetchMedia();
  }, [fetchMedia]);

  // Clean up thumbnail object URLs on unmount
  React.useEffect(() => {
    return () => {
      uploadQueue.forEach((item) => {
        if (item.thumbnailUrl) URL.revokeObjectURL(item.thumbnailUrl);
      });
    };
  }, [uploadQueue]);

  // Synchronous references to guard against race conditions & double-invocation
  const inFlightIdsRef = React.useRef<Set<string>>(new Set());
  const xhrMapRef = React.useRef<Map<string, XMLHttpRequest>>(new Map());
  const reportedBatchesRef = React.useRef<Set<string>>(new Set());
  const queueRef = React.useRef<UploadQueueItem[]>(uploadQueue);
  queueRef.current = uploadQueue;

  const checkBatchCompletion = React.useCallback(async (batchId: string) => {
    if (!batchId || reportedBatchesRef.current.has(batchId)) return;
    const currentQueue = queueRef.current;
    const batchItems = currentQueue.filter((i) => i.batchId === batchId);
    if (batchItems.length === 0) return;

    const allTerminal = batchItems.every(
      (i) => i.status === "COMPLETED" || i.status === "FAILED" || i.status === "CANCELLED"
    );
    if (!allTerminal) return;

    // Prevent duplicate batch reports
    reportedBatchesRef.current.add(batchId);

    const completed = batchItems.filter((i) => i.status === "COMPLETED");
    const failed = batchItems.filter((i) => i.status === "FAILED" || i.status === "CANCELLED");

    if (batchItems.length > 1 && completed.length > 0) {
      try {
        await fetch("/api/admin/media/batch-complete", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            batchId,
            totalCount: batchItems.length,
            completedCount: completed.length,
            failedCount: failed.length,
            filenames: completed.map((i) => i.name),
            failedNames: failed.map((i) => i.name),
          }),
        });
      } catch (err) {
        console.error("Failed to report batch completion:", err);
      }
    }
  }, []);

  // =========================================================================
  // QUEUED BULK UPLOAD ENGINE (Controlled Concurrency = 2, Pure & Idempotent)
  // =========================================================================

  const processNextUpload = React.useCallback(() => {
    // Strict concurrency limit: max 2 active uploads
    if (inFlightIdsRef.current.size >= 2) return;

    // Synchronously inspect queue from ref
    const currentQueue = queueRef.current;
    const candidate = currentQueue.find(
      (i) => i.status === "QUEUED" && !inFlightIdsRef.current.has(i.id)
    );
    if (!candidate) return;

    // ATOMIC SYNCHRONOUS CLAIM: immediately lock candidate.id
    inFlightIdsRef.current.add(candidate.id);

    // Update state purely (no side effects in setter)
    setUploadQueue((prev) =>
      prev.map((it) =>
        it.id === candidate.id ? { ...it, status: "UPLOADING", progress: 5 } : it
      )
    );

    // Create and configure XHR completely outside of React state updaters
    const xhr = new XMLHttpRequest();
    xhrMapRef.current.set(candidate.id, xhr);

    const formData = new FormData();
    formData.append("file", candidate.file);
    formData.append("alt", candidate.file.name.replace(/\.[^/.]+$/, ""));
    formData.append("uploadId", candidate.id);
    if (candidate.batchId) formData.append("batchId", candidate.batchId);
    if (candidate.batchTotal) formData.append("batchTotal", String(candidate.batchTotal));

    xhr.upload.onprogress = (evt) => {
      if (evt.lengthComputable) {
        const percent = Math.min(80, Math.round((evt.loaded / evt.total) * 80));
        setUploadQueue((q) =>
          q.map((it) => (it.id === candidate.id ? { ...it, progress: percent } : it))
        );
      }
    };

    xhr.upload.onload = () => {
      setUploadQueue((q) =>
        q.map((it) =>
          it.id === candidate.id ? { ...it, status: "PROCESSING", progress: 85 } : it
        )
      );
    };

    const cleanupAndCycle = (batchId?: string) => {
      inFlightIdsRef.current.delete(candidate.id);
      xhrMapRef.current.delete(candidate.id);
      if (batchId) {
        setTimeout(() => checkBatchCompletion(batchId), 50);
      }
      setTimeout(() => processNextUpload(), 50);
    };

    xhr.onload = () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        setUploadQueue((q) =>
          q.map((it) =>
            it.id === candidate.id
              ? { ...it, status: "COMPLETED", progress: 100, xhr: undefined }
              : it
          )
        );
        invalidateAdminCache("media");
        fetchMedia(true);
      } else {
        let errMsg = "Upload rejected";
        try {
          const errJson = JSON.parse(xhr.responseText);
          errMsg = errJson.error || errMsg;
        } catch {}
        setUploadQueue((q) =>
          q.map((it) =>
            it.id === candidate.id
              ? { ...it, status: "FAILED", error: errMsg, xhr: undefined }
              : it
          )
        );
      }
      cleanupAndCycle(candidate.batchId);
    };

    xhr.onerror = () => {
      setUploadQueue((q) =>
        q.map((it) =>
          it.id === candidate.id
            ? { ...it, status: "FAILED", error: "Network transfer failed", xhr: undefined }
            : it
        )
      );
      cleanupAndCycle(candidate.batchId);
    };

    xhr.onabort = () => {
      setUploadQueue((q) =>
        q.map((it) =>
          it.id === candidate.id ? { ...it, status: "CANCELLED", xhr: undefined } : it
        )
      );
      cleanupAndCycle(candidate.batchId);
    };

    xhr.open("POST", "/api/admin/media");
    xhr.send(formData);

    // If concurrency slot is still available, schedule next upload
    if (inFlightIdsRef.current.size < 2) {
      setTimeout(() => processNextUpload(), 10);
    }
  }, [fetchMedia, checkBatchCompletion]);

  // Keep concurrency worker cycling when queue changes
  React.useEffect(() => {
    const hasPending = uploadQueue.some((i) => i.status === "QUEUED");
    if (hasPending && inFlightIdsRef.current.size < 2) {
      processNextUpload();
    }
  }, [uploadQueue, processNextUpload]);

  const addFilesToQueue = (files: FileList | File[]) => {
    const validFiles: UploadQueueItem[] = [];
    const batchId = `batch_${crypto.randomUUID()}`;
    const seenFingerprintsInBatch = new Set<string>();

    const activeFingerprints = new Set(
      queueRef.current
        .filter(
          (i) =>
            i.status === "QUEUED" ||
            i.status === "UPLOADING" ||
            i.status === "PROCESSING"
        )
        .map((i) => i.fingerprint)
    );

    for (let i = 0; i < files.length; i++) {
      const file = files[i];
      if (!file.type.startsWith("image/")) {
        toast.error(`"${file.name}" is not an accepted image file`);
        continue;
      }

      const fingerprint = `${file.name}:${file.size}:${file.lastModified}:${file.type}`;
      if (seenFingerprintsInBatch.has(fingerprint)) {
        toast.warning(`"${file.name}" was selected multiple times in this batch. Skipped duplicate.`);
        continue;
      }
      if (activeFingerprints.has(fingerprint)) {
        toast.warning(`"${file.name}" is already in the upload queue.`);
        continue;
      }

      seenFingerprintsInBatch.add(fingerprint);
      validFiles.push({
        id: `upl_${crypto.randomUUID()}`,
        batchId,
        batchTotal: 0, // will set below
        fingerprint,
        file,
        name: file.name,
        size: file.size,
        thumbnailUrl: URL.createObjectURL(file),
        status: "QUEUED",
        progress: 0,
      });
    }

    if (validFiles.length > 0) {
      validFiles.forEach((f) => {
        f.batchTotal = validFiles.length;
      });
      setUploadQueue((prev) => [...prev, ...validFiles]);
      setIsQueueOpen(true);
      toast.info(`Added ${validFiles.length} file(s) to upload queue`);
    }
  };

  const cancelUploadItem = (id: string) => {
    if (xhrMapRef.current.has(id)) {
      xhrMapRef.current.get(id)?.abort();
    }
    inFlightIdsRef.current.delete(id);
    xhrMapRef.current.delete(id);
    setUploadQueue((prev) =>
      prev.map((item) => (item.id === id ? { ...item, status: "CANCELLED" } : item))
    );
    setTimeout(() => processNextUpload(), 50);
  };

  const retryUploadItem = (id: string) => {
    inFlightIdsRef.current.delete(id);
    xhrMapRef.current.delete(id);
    setUploadQueue((prev) =>
      prev.map((item) => {
        if (item.id === id) {
          // Re-use same id (uploadId) for server idempotency!
          return { ...item, status: "QUEUED", progress: 0, error: undefined };
        }
        return item;
      })
    );
    setTimeout(() => processNextUpload(), 50);
  };

  const clearCompletedQueue = () => {
    setUploadQueue((prev) =>
      prev.filter((i) => i.status !== "COMPLETED" && i.status !== "CANCELLED")
    );
    if (uploadQueue.every((i) => i.status === "COMPLETED" || i.status === "CANCELLED")) {
      setIsQueueOpen(false);
    }
  };

  // Drag & drop handlers
  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(true);
  };

  const handleDragLeave = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(false);
  };

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault();
    setIsDragging(false);
    if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
      addFilesToQueue(e.dataTransfer.files);
    }
  };

  // Replacement
  const handleReplaceFile = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file || !selectedItem) return;

    try {
      setReplacing(true);
      const formData = new FormData();
      formData.append("file", file);
      formData.append("replaceMediaId", selectedItem.id);

      const res = await fetch("/api/admin/media", {
        method: "POST",
        body: formData,
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "Replacement failed");

      invalidateAdminCache("media");
      toast.success("Asset replaced successfully!");
      setSelectedItem(data.media);
      fetchMedia(true);
    } catch (err: any) {
      toast.error(err.message || "Replacement failed.");
    } finally {
      setReplacing(false);
      e.target.value = "";
    }
  };

  // Modal inspection
  const handleSelectItem = async (item: MediaItem) => {
    setSelectedItem(item);
    setEditAlt(item.alt || "");
    setEditCaption(item.caption || "");
    setAssetUsage(null);
    setReferencingPosts([]);
    try {
      const res = await fetch(`/api/admin/media/${item.id}`);
      if (res.ok) {
        const data = await res.json();
        setReferencingPosts(data.referencingPosts || []);
        setAssetUsage(data.usage || null);
      }
    } catch {
      setReferencingPosts([]);
      setAssetUsage(null);
    }
  };

  // Save metadata
  const handleSaveMeta = async () => {
    if (!selectedItem) return;
    try {
      setSavingMeta(true);
      const res = await fetch(`/api/admin/media/${selectedItem.id}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ alt: editAlt, caption: editCaption }),
      });
      if (!res.ok) throw new Error("Failed to update metadata");
      invalidateAdminCache("media");
      toast.success("Metadata updated!");
      fetchMedia(true);
    } catch (err: any) {
      toast.error(err.message || "Save failed");
    } finally {
      setSavingMeta(false);
    }
  };

  // Single deletion prompt
  const promptDelete = async (item: MediaItem) => {
    try {
      const res = await fetch(`/api/admin/media/${item.id}`);
      const data = await res.json();
      setDeleteWarningPosts(data.referencingPosts || []);
      setItemToDelete(item);
    } catch {
      setItemToDelete(item);
      setDeleteWarningPosts([]);
    }
  };

  const confirmDelete = async () => {
    if (!itemToDelete) return;
    try {
      setDeleting(true);
      const res = await fetch(`/api/admin/media/${itemToDelete.id}?force=true`, {
        method: "DELETE",
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "Delete failed");

      invalidateAdminCache("media");
      toast.success("Media asset deleted.");
      setItemToDelete(null);
      if (selectedItem?.id === itemToDelete.id) setSelectedItem(null);
      setSelectedIds((prev) => {
        const next = new Set(prev);
        next.delete(itemToDelete.id);
        return next;
      });
      fetchMedia(true);
    } catch (err: any) {
      toast.error(err.message || "Failed to delete");
    } finally {
      setDeleting(false);
    }
  };

  // =========================================================================
  // MULTI-SELECTION & BULK DELETION
  // =========================================================================

  const toggleSelect = (id: string, e: React.MouseEvent) => {
    e.stopPropagation();
    setSelectedIds((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  const selectAllVisible = () => {
    if (selectedIds.size === items.length) {
      setSelectedIds(new Set());
    } else {
      setSelectedIds(new Set(items.map((i) => i.id)));
    }
  };

  const clearSelection = () => {
    setSelectedIds(new Set());
  };

  // Bulk Delete Preflight Check
  const openBulkDeleteConfirmation = async () => {
    if (selectedIds.size === 0) return;
    setShowBulkDeleteModal(true);
    setBulkDeletePreflight({
      checking: true,
      safeCount: 0,
      inUseCount: 0,
      inUseDetails: [],
    });

    try {
      // Inspect selected items against post references
      const selectedList = items.filter((i) => selectedIds.has(i.id));
      let inUseCount = 0;
      let safeCount = 0;
      const inUseDetails: { id: string; filename: string; reason: string }[] = [];

      for (const asset of selectedList) {
        if (asset.usedInPosts && asset.usedInPosts.length > 0) {
          inUseCount++;
          inUseDetails.push({
            id: asset.id,
            filename: asset.filename,
            reason: `Referenced by ${asset.usedInPosts.length} article(s)`,
          });
        } else {
          safeCount++;
        }
      }

      setBulkDeletePreflight({
        checking: false,
        safeCount,
        inUseCount,
        inUseDetails,
      });
    } catch (e) {
      setBulkDeletePreflight({
        checking: false,
        safeCount: selectedIds.size,
        inUseCount: 0,
        inUseDetails: [],
      });
    }
  };

  const executeBulkDelete = async () => {
    try {
      setBulkDeleting(true);
      const res = await fetch("/api/admin/media/bulk-delete", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ ids: Array.from(selectedIds) }),
      });

      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "Bulk deletion failed");

      invalidateAdminCache("media");
      const deletedCount = data.deleted?.length || 0;
      const skippedCount = data.skipped?.length || 0;

      if (deletedCount > 0 && skippedCount > 0) {
        toast.success(
          `Successfully deleted ${deletedCount} asset(s). ${skippedCount} skipped (in active use).`
        );
      } else if (deletedCount > 0) {
        toast.success(`Successfully deleted ${deletedCount} asset(s).`);
      } else {
        toast.warning("No assets were deleted because all selected items are in active use.");
      }

      setShowBulkDeleteModal(false);
      setSelectedIds(new Set());
      fetchMedia(true);
    } catch (err: any) {
      toast.error(err.message || "Bulk deletion failed");
    } finally {
      setBulkDeleting(false);
    }
  };

  const copyUrl = (url: string) => {
    navigator.clipboard.writeText(url);
    toast.success("Media URL copied to clipboard!");
  };

  // Aggregate progress calculation
  const totalQueueCount = uploadQueue.length;
  const completedQueueCount = uploadQueue.filter((i) => i.status === "COMPLETED").length;
  const inProgressQueue = uploadQueue.filter(
    (i) => i.status === "UPLOADING" || i.status === "PROCESSING" || i.status === "QUEUED"
  );
  const aggregateProgress =
    totalQueueCount === 0
      ? 0
      : Math.round(
          uploadQueue.reduce((acc, curr) => acc + (curr.progress || 0), 0) / totalQueueCount
        );

  return (
    <div
      onDragOver={handleDragOver}
      onDragLeave={handleDragLeave}
      onDrop={handleDrop}
      className="space-y-6 min-h-[85vh] relative"
    >
      {/* Drag & Drop Overlay */}
      {isDragging && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-cyan-950/80 backdrop-blur-xs border-4 border-dashed border-cyan-400 p-6 pointer-events-none transition-all animate-in fade-in duration-150">
          <div className="text-center text-white space-y-3">
            <Upload className="h-16 w-16 mx-auto animate-bounce text-cyan-300" />
            <h2 className="text-2xl font-bold">Drop files here to upload</h2>
            <p className="text-sm text-cyan-200">
              Multiple PNG, JPEG, or WebP images will be validated and converted to WebP automatically.
            </p>
          </div>
        </div>
      )}

      {/* Header & Upload Button */}
      <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
        <div>
          <div className="flex items-center gap-2">
            <h1 className="text-2xl font-bold tracking-tight text-neutral-900 dark:text-white">
              Media Library
            </h1>
            <span className="rounded-full bg-cyan-100 px-2 py-0.5 text-[9px] font-bold text-cyan-800 uppercase tracking-wider dark:bg-cyan-950/60 dark:text-cyan-300">
              Cloudinary WebP Pipeline
            </span>
          </div>
          <p className="text-xs text-neutral-500 mt-0.5">
            Multi-file upload queue, automated WebP optimization, reference tracking, and bulk operations.
          </p>
        </div>

        <div className="flex items-center gap-2">
          {/* Upload Queue Trigger if queue active */}
          {uploadQueue.length > 0 && (
            <Button
              variant="outline"
              size="sm"
              onClick={() => setIsQueueOpen((prev) => !prev)}
              className="text-xs flex items-center gap-1.5 shadow-xs"
            >
              {inProgressQueue.length > 0 && (
                <RefreshCw className="h-3 w-3 animate-spin text-cyan-600" />
              )}
              <span>
                Upload Queue ({completedQueueCount}/{totalQueueCount})
              </span>
            </Button>
          )}

          {/* Multiple File Upload Button */}
          <label className="cursor-pointer">
            <input
              ref={fileInputRef}
              type="file"
              multiple
              accept="image/png,image/jpeg,image/webp,image/gif,image/bmp,image/tiff,image/avif"
              onChange={(e) => {
                if (e.target.files && e.target.files.length > 0) {
                  addFilesToQueue(e.target.files);
                  e.target.value = "";
                }
              }}
              className="hidden"
            />
            <span className="inline-flex items-center gap-1.5 rounded-lg bg-neutral-900 px-3.5 py-2 text-xs font-semibold text-white shadow-xs hover:bg-neutral-800 dark:bg-white dark:text-neutral-900 transition">
              <Upload className="h-3.5 w-3.5" />
              <span>Upload Images</span>
            </span>
          </label>
        </div>
      </div>

      {/* Search & Bulk Selection Bar */}
      <div className="flex flex-col sm:flex-row items-stretch sm:items-center justify-between gap-3 rounded-xl border border-neutral-200 bg-white p-3 shadow-xs dark:border-neutral-800 dark:bg-neutral-900">
        <div className="flex items-center gap-3 flex-1 max-w-md">
          <div className="relative flex-1">
            <Search className="absolute left-2.5 top-2.5 h-3.5 w-3.5 text-neutral-400" />
            <Input
              placeholder="Search by filename or alt text..."
              value={search}
              onChange={(e) => setSearch(e.target.value)}
              className="h-8 pl-8 text-xs"
            />
          </div>
        </div>

        <div className="flex items-center gap-2 justify-between sm:justify-end">
          <Button
            variant="ghost"
            size="sm"
            onClick={selectAllVisible}
            className="h-8 text-xs text-neutral-600 dark:text-neutral-300 flex items-center gap-1.5"
          >
            {selectedIds.size > 0 && selectedIds.size === items.length ? (
              <CheckSquare className="h-3.5 w-3.5 text-neutral-900 dark:text-white" />
            ) : (
              <Square className="h-3.5 w-3.5" />
            )}
            <span>
              {selectedIds.size > 0 && selectedIds.size === items.length
                ? "Deselect All"
                : `Select All (${items.length})`}
            </span>
          </Button>

          <span className="text-xs text-neutral-400 border-l border-neutral-200 pl-3 dark:border-neutral-800">
            {items.length} asset{items.length === 1 ? "" : "s"}
          </span>
        </div>
      </div>

      {/* Upload Queue Panel */}
      {isQueueOpen && uploadQueue.length > 0 && (
        <div className="rounded-xl border border-cyan-200 bg-cyan-50/40 p-4 dark:border-cyan-900/50 dark:bg-cyan-950/20 space-y-3 transition-all">
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-2">
              <span className="font-semibold text-xs text-cyan-950 dark:text-cyan-100">
                Uploading {completedQueueCount} of {totalQueueCount} file(s)
              </span>
              <span className="text-[11px] text-cyan-800/80 dark:text-cyan-300/80">
                • Overall {aggregateProgress}%
              </span>
            </div>

            <div className="flex items-center gap-2">
              {completedQueueCount > 0 && (
                <button
                  type="button"
                  onClick={clearCompletedQueue}
                  className="text-[11px] text-cyan-700 hover:underline dark:text-cyan-300"
                >
                  Clear Completed
                </button>
              )}
              <button
                type="button"
                onClick={() => setIsQueueOpen(false)}
                className="text-neutral-400 hover:text-neutral-700 dark:hover:text-neutral-200"
              >
                <X className="h-4 w-4" />
              </button>
            </div>
          </div>

          {/* Aggregate Progress Bar */}
          <div className="h-1.5 w-full overflow-hidden rounded-full bg-cyan-200/60 dark:bg-cyan-900/60">
            <div
              className="h-full bg-cyan-600 transition-all duration-300"
              style={{ width: `${aggregateProgress}%` }}
            />
          </div>

          {/* Queue List */}
          <div className="max-h-48 overflow-y-auto space-y-2 pr-1">
            {uploadQueue.map((item) => (
              <div
                key={item.id}
                className="flex items-center justify-between gap-3 rounded-lg border border-neutral-200/70 bg-white p-2.5 text-xs dark:border-neutral-800 dark:bg-neutral-900"
              >
                <div className="flex items-center gap-2.5 min-w-0 flex-1">
                  <div className="h-8 w-8 rounded overflow-hidden bg-neutral-100 shrink-0 dark:bg-neutral-800 border border-neutral-200 dark:border-neutral-750">
                    <img
                      src={item.thumbnailUrl}
                      alt={item.name}
                      className="h-full w-full object-cover"
                    />
                  </div>
                  <div className="min-w-0 flex-1">
                    <p className="truncate font-medium text-neutral-800 dark:text-neutral-200">
                      {item.name}
                    </p>
                    <div className="flex items-center gap-2 text-[10px] text-neutral-400">
                      <span>{(item.size / 1024).toFixed(0)} KB</span>
                      <span>•</span>
                      <span
                        className={
                          item.status === "COMPLETED"
                            ? "text-emerald-600 font-medium"
                            : item.status === "FAILED"
                            ? "text-rose-600 font-medium"
                            : item.status === "PROCESSING"
                            ? "text-purple-600 font-medium"
                            : "text-cyan-600"
                        }
                      >
                        {item.status === "QUEUED"
                          ? "Waiting in queue..."
                          : item.status === "UPLOADING"
                          ? `Uploading (${item.progress}%)`
                          : item.status === "PROCESSING"
                          ? "Converting & Storing..."
                          : item.status === "COMPLETED"
                          ? "Completed"
                          : item.status === "CANCELLED"
                          ? "Cancelled"
                          : `Failed: ${item.error || "Error"}`}
                      </span>
                    </div>
                  </div>
                </div>

                {/* Progress bar and control button */}
                <div className="flex items-center gap-2 shrink-0">
                  {(item.status === "UPLOADING" || item.status === "PROCESSING") && (
                    <div className="w-16 h-1.5 overflow-hidden rounded-full bg-neutral-100 dark:bg-neutral-800">
                      <div
                        className="h-full bg-cyan-600 transition-all duration-200"
                        style={{ width: `${item.progress}%` }}
                      />
                    </div>
                  )}

                  {item.status === "FAILED" && (
                    <button
                      type="button"
                      onClick={() => retryUploadItem(item.id)}
                      className="text-neutral-500 hover:text-neutral-900 dark:hover:text-white p-1"
                      title="Retry upload"
                    >
                      <RotateCcw className="h-3.5 w-3.5" />
                    </button>
                  )}

                  {(item.status === "QUEUED" ||
                    item.status === "UPLOADING" ||
                    item.status === "PROCESSING") && (
                    <button
                      type="button"
                      onClick={() => cancelUploadItem(item.id)}
                      className="text-neutral-400 hover:text-rose-600 p-1"
                      title="Cancel upload"
                    >
                      <X className="h-3.5 w-3.5" />
                    </button>
                  )}

                  {item.status === "COMPLETED" && (
                    <CheckCircle2 className="h-4 w-4 text-emerald-600 shrink-0" />
                  )}
                </div>
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Media Grid */}
      <div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4">
        {loading ? (
          <div className="col-span-full py-16 text-center text-xs text-neutral-400">
            <RefreshCw className="h-5 w-5 animate-spin mx-auto mb-2 text-neutral-400" />
            Loading media assets...
          </div>
        ) : items.length === 0 ? (
          <div className="col-span-full rounded-2xl border-2 border-dashed border-neutral-200 p-12 text-center dark:border-neutral-800">
            <ImageIcon className="mx-auto h-12 w-12 text-neutral-300 dark:text-neutral-700" />
            <p className="mt-3 text-sm font-semibold text-neutral-800 dark:text-neutral-200">
              No media assets found
            </p>
            <p className="text-xs text-neutral-500 mt-1 max-w-sm mx-auto">
              Select or drag and drop PNG, JPEG, or WebP images to automatically optimize and upload them.
            </p>
          </div>
        ) : (
          items.map((item) => {
            const isSelected = selectedIds.has(item.id);
            return (
              <div
                key={item.id}
                onClick={() => handleSelectItem(item)}
                className={`group relative aspect-square overflow-hidden rounded-xl border bg-neutral-100 dark:bg-neutral-800 cursor-pointer transition-all duration-150 hover:shadow-md ${
                  isSelected
                    ? "border-cyan-600 ring-2 ring-cyan-600 dark:border-cyan-400 dark:ring-cyan-400 shadow-sm"
                    : selectedItem?.id === item.id
                    ? "border-neutral-900 ring-2 ring-neutral-900 dark:border-white dark:ring-white"
                    : "border-neutral-200 dark:border-neutral-800"
                }`}
              >
                {/* Selection Checkbox Overlay */}
                <div
                  onClick={(e) => toggleSelect(item.id, e)}
                  className={`absolute top-2 left-2 z-10 rounded-md p-1 backdrop-blur-xs transition-opacity ${
                    isSelected
                      ? "bg-cyan-600 text-white opacity-100 shadow-xs"
                      : "bg-black/40 text-white opacity-0 group-hover:opacity-100 hover:bg-black/60"
                  }`}
                  title={isSelected ? "Deselect" : "Select"}
                >
                  {isSelected ? (
                    <CheckSquare className="h-4 w-4" />
                  ) : (
                    <Square className="h-4 w-4" />
                  )}
                </div>

                {/* Reference Count Badge */}
                {item.usedInPosts && item.usedInPosts.length > 0 && (
                  <div className="absolute top-2 right-2 z-10 rounded-full bg-black/60 backdrop-blur-xs px-2 py-0.5 text-[9px] font-bold text-white shadow-xs">
                    {item.usedInPosts.length} link{item.usedInPosts.length === 1 ? "" : "s"}
                  </div>
                )}

                <img
                  src={item.url}
                  alt={item.alt || item.filename}
                  className="h-full w-full object-cover transition group-hover:scale-105"
                  loading="lazy"
                />

                <div className="absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/85 via-black/45 to-transparent p-2.5 text-white opacity-0 group-hover:opacity-100 transition">
                  <p className="truncate text-[11px] font-semibold">{item.filename}</p>
                  <p className="text-[9px] text-neutral-300">
                    {(item.size / 1024).toFixed(0)} KB • {item.mimeType.replace("image/", "")}
                  </p>
                </div>
              </div>
            );
          })
        )}
      </div>

      {/* Sticky Bulk Action Toolbar (appears when >= 1 selected) */}
      {selectedIds.size > 0 && (
        <div className="fixed bottom-4 left-4 right-4 z-40 sm:left-auto sm:right-8 sm:bottom-8 sm:w-auto animate-in slide-in-from-bottom-3 duration-200">
          <div className="flex items-center justify-between gap-4 rounded-2xl border border-neutral-800 bg-neutral-900/95 px-4 py-2.5 text-white shadow-2xl backdrop-blur-md dark:border-neutral-700 dark:bg-neutral-900/95">
            <span className="text-xs font-semibold whitespace-nowrap">
              {selectedIds.size} asset{selectedIds.size === 1 ? "" : "s"} selected
            </span>

            <div className="flex items-center gap-2">
              <Button
                variant="ghost"
                size="sm"
                onClick={clearSelection}
                className="h-8 text-xs text-neutral-300 hover:text-white hover:bg-neutral-800"
              >
                Clear
              </Button>
              <Button
                variant="destructive"
                size="sm"
                onClick={openBulkDeleteConfirmation}
                className="h-8 text-xs flex items-center gap-1.5 shadow-xs"
              >
                <Trash2 className="h-3.5 w-3.5" />
                <span>Delete Selected</span>
              </Button>
            </div>
          </div>
        </div>
      )}

      {/* Selected Item Detail Modal */}
      <Dialog open={!!selectedItem} onOpenChange={(open) => !open && setSelectedItem(null)}>
        <DialogContent className="max-w-[95vw] sm:max-w-xl max-h-[90dvh] flex flex-col p-0 overflow-hidden rounded-2xl border border-neutral-200 dark:border-neutral-800 bg-white dark:bg-neutral-900 shadow-2xl">
          {selectedItem && (
            <div className="flex flex-col h-full max-h-[90dvh] overflow-hidden">
              {/* Sticky Modal Header */}
              <div className="p-5 pb-3 border-b border-neutral-100 dark:border-neutral-800 shrink-0 bg-white dark:bg-neutral-900">
                <DialogHeader>
                  <DialogTitle className="text-base font-bold truncate">
                    {selectedItem.filename}
                  </DialogTitle>
                  <DialogDescription suppressHydrationWarning className="text-xs">
                    Uploaded by {selectedItem.uploadedBy} on{" "}
                    {new Date(selectedItem.uploadedAt).toLocaleDateString("en-US")}
                  </DialogDescription>
                </DialogHeader>
              </div>

              {/* Scrollable Content Body */}
              <div className="overflow-y-auto p-5 space-y-4 text-xs flex-1 overscroll-contain">
                <div className="relative aspect-video w-full overflow-hidden rounded-lg bg-neutral-100 dark:bg-neutral-800 border border-neutral-200 dark:border-neutral-800">
                  <img
                    src={selectedItem.url}
                    alt={selectedItem.alt}
                    className="h-full w-full object-contain"
                  />
                </div>

                <div className="grid grid-cols-2 gap-2 text-neutral-600 dark:text-neutral-400 text-[11px]">
                  <div>
                    <strong>Size:</strong> {(selectedItem.size / 1024).toFixed(1)} KB
                  </div>
                  <div>
                    <strong>Type:</strong> {selectedItem.mimeType}
                  </div>
                  {selectedItem.publicId && (
                    <div className="col-span-2 flex items-center gap-1">
                      <strong className="shrink-0">Public ID:</strong>
                      <code className="truncate rounded bg-neutral-100 px-1 py-0.5 dark:bg-neutral-800 text-[10px]">
                        {selectedItem.publicId}
                      </code>
                    </div>
                  )}
                  <div className="col-span-2 flex items-center gap-1">
                    <strong className="shrink-0">URL:</strong>
                    <code className="truncate rounded bg-neutral-100 px-1 py-0.5 dark:bg-neutral-800 text-[10px]">
                      {selectedItem.url}
                    </code>
                    <button
                      onClick={() => copyUrl(selectedItem.url)}
                      className="text-cyan-600 hover:underline shrink-0 ml-1 font-medium"
                    >
                      Copy
                    </button>
                  </div>
                </div>

                {/* Used In Posts / Content Reference Tracking */}
                <div className="rounded-xl border border-neutral-200 bg-neutral-50 p-3.5 dark:border-neutral-800 dark:bg-neutral-950">
                  <div className="font-semibold text-neutral-800 dark:text-neutral-200 flex items-center justify-between">
                    <div className="flex items-center gap-1.5">
                      <FileText className="h-3.5 w-3.5 text-cyan-600 dark:text-cyan-400" />
                      <span>Asset Usage & References</span>
                    </div>
                    <span
                      className={`text-[10px] font-bold px-2 py-0.5 rounded-full ${
                        (assetUsage?.usageCount || referencingPosts.length) > 0
                          ? "bg-emerald-100 text-emerald-800 dark:bg-emerald-950/60 dark:text-emerald-300"
                          : "bg-amber-100 text-amber-800 dark:bg-amber-950/60 dark:text-amber-300"
                      }`}
                    >
                      {(assetUsage?.usageCount || referencingPosts.length) > 0
                        ? `Used (${assetUsage?.usageCount || referencingPosts.length})`
                        : "Orphan Asset"}
                    </span>
                  </div>

                  {!(assetUsage?.isUsed || referencingPosts.length > 0) ? (
                    <p className="mt-1.5 text-neutral-500 text-[11px] leading-relaxed">
                      Orphan asset: Not currently referenced by any articles, authors, or categories. Safe to delete.
                    </p>
                  ) : (
                    <div className="mt-2.5 space-y-2 text-[11px]">
                      {assetUsage?.referencingEntities?.articles?.length > 0 ? (
                        <div>
                          <span className="font-semibold text-neutral-700 dark:text-neutral-300">
                            Articles ({assetUsage.referencingEntities.articles.length}):
                          </span>
                          <ul className="mt-1 list-disc list-inside space-y-0.5 text-neutral-600 dark:text-neutral-400">
                            {assetUsage.referencingEntities.articles.map((art: any, i: number) => (
                              <li key={i} className="truncate">
                                <a
                                  href={`/admin/posts/${art.id}`}
                                  className="hover:underline text-cyan-600 dark:text-cyan-400"
                                >
                                  {art.title}
                                </a>
                              </li>
                            ))}
                          </ul>
                        </div>
                      ) : referencingPosts.length > 0 ? (
                        <div>
                          <span className="font-semibold text-neutral-700 dark:text-neutral-300">
                            Articles ({referencingPosts.length}):
                          </span>
                          <ul className="mt-1 list-disc list-inside space-y-0.5 text-neutral-600 dark:text-neutral-400">
                            {referencingPosts.map((title, i) => (
                              <li key={i} className="truncate">
                                {title}
                              </li>
                            ))}
                          </ul>
                        </div>
                      ) : null}
                    </div>
                  )}
                </div>

                {/* Metadata editor */}
                <div className="space-y-2">
                  <div className="space-y-1">
                    <label className="font-semibold text-neutral-700 dark:text-neutral-300">
                      Alt Text (Accessibility)
                    </label>
                    <Input
                      value={editAlt}
                      onChange={(e) => setEditAlt(e.target.value)}
                      className="text-xs"
                    />
                  </div>
                  <div className="space-y-1">
                    <label className="font-semibold text-neutral-700 dark:text-neutral-300">
                      Caption (Optional)
                    </label>
                    <Input
                      value={editCaption}
                      onChange={(e) => setEditCaption(e.target.value)}
                      className="text-xs"
                    />
                  </div>
                </div>
              </div>

              {/* Sticky Modal Footer */}
              <div className="p-4 border-t border-neutral-100 dark:border-neutral-800 bg-neutral-50/95 dark:bg-neutral-900/95 shrink-0">
                <DialogFooter className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
                  <div className="flex items-center gap-2">
                    <Button
                      variant="destructive"
                      size="sm"
                      onClick={() => promptDelete(selectedItem)}
                      className="text-xs"
                    >
                      Delete Asset
                    </Button>
                    <label className="cursor-pointer">
                      <input
                        type="file"
                        accept="image/png,image/jpeg,image/webp,image/gif,image/bmp,image/tiff,image/avif"
                        onChange={handleReplaceFile}
                        className="hidden"
                        disabled={replacing}
                      />
                      <span className="inline-flex items-center gap-1.5 rounded-md border border-neutral-200 bg-white px-3 py-1.5 text-xs font-medium text-neutral-700 hover:bg-neutral-50 dark:border-neutral-750 dark:bg-neutral-800 dark:text-neutral-200 dark:hover:bg-neutral-700 transition shadow-xs">
                        <RefreshCw className={`h-3 w-3 ${replacing ? "animate-spin" : ""}`} />
                        <span>{replacing ? "Replacing..." : "Replace Image"}</span>
                      </span>
                    </label>
                  </div>
                  <div className="flex items-center gap-2">
                    <Button
                      variant="outline"
                      size="sm"
                      onClick={() => setSelectedItem(null)}
                      className="text-xs"
                    >
                      Close
                    </Button>
                    <Button
                      size="sm"
                      onClick={handleSaveMeta}
                      disabled={savingMeta}
                      className="bg-neutral-900 text-xs text-white hover:bg-neutral-800 dark:bg-white dark:text-neutral-900 shadow-xs"
                    >
                      {savingMeta ? "Saving..." : "Save Metadata"}
                    </Button>
                  </div>
                </DialogFooter>
              </div>
            </div>
          )}
        </DialogContent>
      </Dialog>

      {/* Single Delete Alert Dialog */}
      <AlertDialog open={!!itemToDelete} onOpenChange={(open) => !open && setItemToDelete(null)}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Delete Media Asset?</AlertDialogTitle>
            <AlertDialogDescription asChild>
              <div>
                {deleteWarningPosts.length > 0 ? (
                  <div className="space-y-2 text-amber-700 dark:text-amber-300">
                    <div className="flex items-center gap-1.5 font-bold">
                      <AlertTriangle className="h-4 w-4" />
                      <span>Warning: Asset is used in {deleteWarningPosts.length} article(s)!</span>
                    </div>
                    <p className="text-xs">
                      Deleting &ldquo;{itemToDelete?.filename}&rdquo; will break image display in:
                    </p>
                    <ul className="list-disc list-inside text-xs">
                      {deleteWarningPosts.map((t, i) => (
                        <li key={i} className="truncate">
                          {t}
                        </li>
                      ))}
                    </ul>
                  </div>
                ) : (
                  <span>
                    Are you sure you want to delete &ldquo;{itemToDelete?.filename}&rdquo;? This will
                    permanently remove the file from storage and MongoDB.
                  </span>
                )}
              </div>
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={deleting}>Cancel</AlertDialogCancel>
            <AlertDialogAction
              onClick={confirmDelete}
              disabled={deleting}
              className="bg-red-600 text-white hover:bg-red-700"
            >
              {deleting ? "Deleting..." : "Confirm & Delete"}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      {/* Reference-Protected Bulk Deletion Dialog */}
      <AlertDialog
        open={showBulkDeleteModal}
        onOpenChange={(open) => !open && setShowBulkDeleteModal(false)}
      >
        <AlertDialogContent className="max-w-md">
          <AlertDialogHeader>
            <AlertDialogTitle>Delete {selectedIds.size} Media Assets?</AlertDialogTitle>
            <AlertDialogDescription asChild>
              <div className="space-y-3 text-xs">
                {bulkDeletePreflight.checking ? (
                  <div className="flex items-center gap-2 py-3 text-neutral-400">
                    <RefreshCw className="h-4 w-4 animate-spin text-neutral-400" />
                    <span>Verifying article references and usage across database...</span>
                  </div>
                ) : bulkDeletePreflight.inUseCount > 0 ? (
                  <div className="space-y-2.5">
                    <div className="rounded-lg border border-amber-200 bg-amber-50 p-3 text-amber-800 dark:border-amber-900/50 dark:bg-amber-950/40 dark:text-amber-200">
                      <div className="flex items-center gap-1.5 font-bold">
                        <AlertTriangle className="h-4 w-4 shrink-0 text-amber-600" />
                        <span>Reference Protection Active</span>
                      </div>
                      <p className="mt-1 text-[11px] leading-relaxed">
                        <strong>{bulkDeletePreflight.safeCount}</strong> asset(s) are safe to delete.{" "}
                        <strong>{bulkDeletePreflight.inUseCount}</strong> asset(s) are actively referenced by
                        published articles and will be skipped to protect website integrity.
                      </p>
                    </div>

                    <div className="max-h-28 overflow-y-auto space-y-1 rounded border border-neutral-200 p-2 dark:border-neutral-800">
                      {bulkDeletePreflight.inUseDetails.map((item) => (
                        <div
                          key={item.id}
                          className="flex items-center justify-between text-[10px] text-neutral-600 dark:text-neutral-400 truncate"
                        >
                          <span className="truncate font-medium">{item.filename}</span>
                          <span className="text-amber-600 shrink-0 ml-2">{item.reason}</span>
                        </div>
                      ))}
                    </div>
                  </div>
                ) : (
                  <p className="text-neutral-600 dark:text-neutral-400 leading-relaxed">
                    None of the {selectedIds.size} selected assets are actively referenced by published articles.
                    This will permanently remove them from Cloudinary storage and MongoDB.
                  </p>
                )}
              </div>
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={bulkDeleting}>Cancel</AlertDialogCancel>
            <AlertDialogAction
              onClick={executeBulkDelete}
              disabled={bulkDeleting || bulkDeletePreflight.safeCount === 0}
              className="bg-red-600 text-white hover:bg-red-700"
            >
              {bulkDeleting
                ? "Deleting..."
                : bulkDeletePreflight.inUseCount > 0
                ? `Delete ${bulkDeletePreflight.safeCount} Available Asset(s)`
                : `Confirm & Delete (${selectedIds.size})`}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}
