"use client";

/**
 * CarImageModal — full per-car image management panel.
 *
 * Features:
 *  • View current gallery with thumbnails
 *  • Set primary image (crown icon)
 *  • Drag-to-reorder gallery
 *  • Upload new images directly
 *  • Pick images from Media Library (MediaPicker)
 *  • Unassign image from car (does NOT delete from library)
 */

import { useCallback, useEffect, useRef, useState } from "react";
import Image from "next/image";
import {
  X, Crown, Trash2, Upload, Library, Loader2,
  CheckCircle2, AlertCircle, GripVertical, Star,
  ImageIcon,
} from "lucide-react";
import { cn } from "@/lib/utils";
import { getAdminToken } from "@/lib/adminAuth";
import { resolveUploadUrl } from "@/lib/uploadUrl";
import MediaPicker, { PickedMedia } from "./MediaPicker";

const API = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000";

interface GalleryImage {
  mediaId:      string;
  url:          string;
  thumbnailUrl: string;
  tabletUrl:    string;
  mobileUrl:    string;
  alt:          string;
  isPrimary:    boolean;
  category:     string;
  order:        number;
}

interface CarImageData {
  carId:        string;
  name:         string;
  brand:        string;
  primaryImage: string | null;
  imageStatus:  string;
  imageGallery: GalleryImage[];
  imageCount:   number;
}

interface Props {
  carId:    string;
  carName:  string;
  brand:    string;
  open:     boolean;
  onClose:  () => void;
  onSaved:  () => void;   // called after any successful mutation so parent can refresh
}

async function apiFetch(path: string, opts: RequestInit = {}) {
  const token = getAdminToken();
  const res   = await fetch(`${API}${path}`, {
    headers: {
      "Content-Type": "application/json",
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
    },
    ...opts,
  });
  if (!res.ok) {
    let msg = `HTTP ${res.status}`;
    try { msg = (await res.json()).detail ?? msg; } catch {}
    throw new Error(msg);
  }
  return res.json();
}

const STATUS_COLOR: Record<string, string> = {
  uploaded:        "bg-green-100 text-green-700",
  partial:         "bg-yellow-100 text-yellow-700",
  pending_upload:  "bg-red-100 text-red-600",
};
const STATUS_LABEL: Record<string, string> = {
  uploaded:        "Uploaded",
  partial:         "Partial",
  pending_upload:  "No Images",
};

export default function CarImageModal({ carId, carName, brand, open, onClose, onSaved }: Props) {
  const [data,         setData]         = useState<CarImageData | null>(null);
  const [loading,      setLoading]      = useState(false);
  const [toast,        setToast]        = useState<{ msg: string; ok: boolean } | null>(null);
  const [pickerOpen,   setPickerOpen]   = useState(false);
  const [dragging,     setDragging]     = useState<string | null>(null);
  const [dragOver,     setDragOver]     = useState<string | null>(null);
  const [uploading,    setUploading]    = useState(false);
  const [uploadPct,    setUploadPct]    = useState(0);
  const fileRef = useRef<HTMLInputElement>(null);

  const showToast = (msg: string, ok = true) => {
    setToast({ msg, ok });
    setTimeout(() => setToast(null), 3000);
  };

  const load = useCallback(async () => {
    if (!carId) return;
    setLoading(true);
    try {
      const d = await apiFetch(`/api/car-images/${carId}`);
      setData(d);
    } catch (e: any) {
      showToast(e.message, false);
    } finally {
      setLoading(false);
    }
  }, [carId]);

  useEffect(() => {
    if (open) load();
  }, [open, load]);

  // ── Set primary ─────────────────────────────────────────────────────────────

  async function setPrimary(mediaId: string) {
    try {
      await apiFetch(`/api/car-images/${carId}/primary`, {
        method: "PATCH",
        body:   JSON.stringify({ mediaId }),
      });
      showToast("Primary image set");
      await load();
      onSaved();
    } catch (e: any) { showToast(e.message, false); }
  }

  // ── Unassign ─────────────────────────────────────────────────────────────────

  async function unassign(mediaId: string) {
    if (!confirm("Remove this image from the car? (Image stays in Media Library)")) return;
    try {
      await apiFetch(`/api/car-images/${carId}/${mediaId}`, { method: "DELETE" });
      showToast("Image removed from car");
      await load();
      onSaved();
    } catch (e: any) { showToast(e.message, false); }
  }

  // ── Assign from media picker ─────────────────────────────────────────────────

  async function handlePickerSelect(picked: PickedMedia[]) {
    if (!picked.length) return;
    try {
      await apiFetch(`/api/car-images/${carId}/assign`, {
        method: "POST",
        body:   JSON.stringify({ mediaIds: picked.map((p) => p.mediaId) }),
      });
      showToast(`${picked.length} image${picked.length !== 1 ? "s" : ""} assigned`);
      await load();
      onSaved();
    } catch (e: any) { showToast(e.message, false); }
  }

  // ── Direct upload ────────────────────────────────────────────────────────────

  function handleFileChange(e: React.ChangeEvent<HTMLInputElement>) {
    const files = Array.from(e.target.files ?? []);
    if (!files.length) return;
    e.target.value = "";
    uploadFiles(files);
  }

  async function uploadFiles(files: File[]) {
    setUploading(true);
    setUploadPct(0);

    const token = getAdminToken();
    let succeeded = 0;

    for (let i = 0; i < files.length; i++) {
      const file = files[i];
      setUploadPct(Math.round(((i) / files.length) * 90));
      try {
        const fd = new FormData();
        fd.append("file", file);
        const res = await fetch(`${API}/api/car-images/${carId}/upload`, {
          method:  "POST",
          headers: token ? { Authorization: `Bearer ${token}` } : {},
          body:    fd,
        });
        if (res.ok) succeeded++;
        else { const d = await res.json(); showToast(d.detail ?? "Upload failed", false); }
      } catch { showToast("Upload error", false); }
    }

    setUploadPct(100);
    await load();
    onSaved();
    setUploading(false);
    if (succeeded > 0) showToast(`${succeeded} image${succeeded !== 1 ? "s" : ""} uploaded`);
  }

  // ── Drag-to-reorder ──────────────────────────────────────────────────────────

  function onDragStart(mediaId: string) { setDragging(mediaId); }
  function onDragEnd()                   { setDragging(null); setDragOver(null); }

  function onDragOverItem(e: React.DragEvent, mediaId: string) {
    e.preventDefault();
    setDragOver(mediaId);
  }

  async function onDropItem(targetMediaId: string) {
    if (!dragging || dragging === targetMediaId || !data) return;
    setDragging(null); setDragOver(null);

    const gallery = [...data.imageGallery];
    const fromIdx = gallery.findIndex((g) => g.mediaId === dragging);
    const toIdx   = gallery.findIndex((g) => g.mediaId === targetMediaId);
    if (fromIdx === -1 || toIdx === -1) return;

    const [moved] = gallery.splice(fromIdx, 1);
    gallery.splice(toIdx, 0, moved);

    // Optimistic update
    setData((prev) => prev ? { ...prev, imageGallery: gallery } : prev);

    try {
      await apiFetch(`/api/car-images/${carId}/reorder`, {
        method: "PATCH",
        body:   JSON.stringify({ orderedMediaIds: gallery.map((g) => g.mediaId) }),
      });
      onSaved();
    } catch (e: any) {
      showToast(e.message, false);
      await load();   // revert
    }
  }

  if (!open) return null;

  const gallery  = data?.imageGallery ?? [];
  const primary  = data?.primaryImage;
  const status   = data?.imageStatus ?? "pending_upload";

  return (
    <>
      <MediaPicker
        open={pickerOpen}
        onClose={() => setPickerOpen(false)}
        onSelect={handlePickerSelect}
        multiSelect
        filterCategory="car"
      />

      {/* Modal backdrop */}
      <div
        className="fixed inset-0 z-[100] flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm"
        onClick={onClose}
      >
        <div
          className="bg-white rounded-3xl shadow-2xl w-full max-w-2xl max-h-[90vh] flex flex-col overflow-hidden"
          onClick={(e) => e.stopPropagation()}
        >
          {/* Header */}
          <div className="flex items-center justify-between gap-3 px-5 sm:px-6 py-4 border-b border-gray-100 shrink-0 min-w-0">
            <div className="flex items-center gap-3 min-w-0 flex-1">
              <div className="w-9 h-9 rounded-xl bg-gradient-to-br from-blue-600 to-cyan-500 flex items-center justify-center shadow shrink-0">
                <ImageIcon className="w-4 h-4 text-white" />
              </div>
              <div className="min-w-0">
                <h2 className="text-sm font-black text-gray-900 truncate">{carName}</h2>
                <div className="flex items-center gap-2 mt-0.5">
                  <span className="text-xs text-gray-400">{brand}</span>
                  <span className={cn(
                    "text-[10px] font-black px-2 py-0.5 rounded-full",
                    STATUS_COLOR[status] ?? STATUS_COLOR.pending_upload
                  )}>
                    {STATUS_LABEL[status] ?? status}
                  </span>
                </div>
              </div>
            </div>
            <button onClick={onClose} className="p-2 rounded-xl hover:bg-gray-100 transition-colors shrink-0" aria-label="Close">
              <X className="w-5 h-5 text-gray-400" />
            </button>
          </div>

          {/* Toast */}
          {toast && (
            <div className={cn(
              "mx-5 mt-4 flex items-center gap-2 px-4 py-2.5 rounded-xl text-sm font-semibold",
              toast.ok ? "bg-green-50 text-green-700 border border-green-200"
                       : "bg-red-50 text-red-700 border border-red-200"
            )}>
            {toast.ok ? <CheckCircle2 className="w-4 h-4 shrink-0" /> : <AlertCircle className="w-4 h-4 shrink-0" />}
            <p className="flex-1 min-w-0 break-words">{toast.msg}</p>
          </div>
        )}

          {/* Body */}
          <div className="flex-1 overflow-y-auto p-5">
            {loading ? (
              <div className="flex items-center justify-center h-40">
                <Loader2 className="w-6 h-6 text-blue-500 animate-spin" />
              </div>
            ) : gallery.length === 0 ? (
              <div className="text-center py-16 bg-gray-50 rounded-2xl border-2 border-dashed border-gray-200">
                <ImageIcon className="w-12 h-12 mx-auto mb-3 text-gray-300" />
                <p className="font-black text-gray-500 text-sm">No images yet</p>
                <p className="text-xs text-gray-400 mt-1">Upload images or pick from the Media Library below</p>
              </div>
            ) : (
              <>
                <p className="text-xs font-bold text-gray-500 mb-3">
                  {gallery.length} image{gallery.length !== 1 ? "s" : ""} · drag to reorder · <span className="text-amber-600">crown = primary</span>
                </p>
                <div className="grid grid-cols-2 sm:grid-cols-3 gap-3">
                  {gallery
                    .slice()
                    .sort((a, b) => a.order - b.order)
                    .map((img) => {
                      const isPrim = img.isPrimary || img.url === primary;
                      return (
                        <div
                          key={img.mediaId}
                          draggable
                          onDragStart={() => onDragStart(img.mediaId)}
                          onDragEnd={onDragEnd}
                          onDragOver={(e) => onDragOverItem(e, img.mediaId)}
                          onDrop={() => onDropItem(img.mediaId)}
                          className={cn(
                            "relative group rounded-2xl overflow-hidden border-2 transition-all",
                            isPrim    ? "border-amber-400 shadow-md"
                                      : "border-gray-100 hover:border-gray-300",
                            dragging === img.mediaId ? "opacity-40 scale-95"
                                                     : "",
                            dragOver === img.mediaId && dragging !== img.mediaId
                              ? "border-blue-400 scale-105"
                              : "",
                          )}
                        >
                          {/* Thumbnail */}
                          <div className="relative aspect-video bg-gray-50">
                            <Image
                              src={resolveUploadUrl(img.thumbnailUrl || img.url)}
                              alt={img.alt || carName}
                              fill
                              className="object-cover"
                              sizes="200px"
                              unoptimized
                            />

                            {/* Drag handle */}
                            <div className="absolute top-1.5 left-1.5 opacity-0 group-hover:opacity-100 transition-opacity cursor-grab active:cursor-grabbing">
                              <div className="w-6 h-6 bg-white/90 rounded-lg flex items-center justify-center shadow-sm">
                                <GripVertical className="w-3.5 h-3.5 text-gray-500" />
                              </div>
                            </div>

                            {/* Primary crown */}
                            {isPrim && (
                              <div className="absolute top-1.5 right-1.5 w-6 h-6 bg-amber-400 rounded-lg flex items-center justify-center shadow-sm">
                                <Crown className="w-3.5 h-3.5 text-white" />
                              </div>
                            )}
                          </div>

                          {/* Actions */}
                          <div className="bg-white px-2 py-1.5 flex items-center justify-between">
                            <p className="text-[10px] text-gray-400 truncate flex-1 mr-1">{img.alt || "car image"}</p>
                            <div className="flex gap-1 shrink-0">
                              {!isPrim && (
                                <button
                                  onClick={() => setPrimary(img.mediaId)}
                                  title="Set as primary"
                                  className="p-1 rounded-lg hover:bg-amber-50 text-gray-300 hover:text-amber-500 transition-colors"
                                >
                                  <Star className="w-3.5 h-3.5" />
                                </button>
                              )}
                              <button
                                onClick={() => unassign(img.mediaId)}
                                title="Remove from car"
                                className="p-1 rounded-lg hover:bg-red-50 text-gray-300 hover:text-red-500 transition-colors"
                              >
                                <Trash2 className="w-3.5 h-3.5" />
                              </button>
                            </div>
                          </div>
                        </div>
                      );
                    })}
                </div>
              </>
            )}
          </div>

          {/* Footer actions */}
          <div className="border-t border-gray-100 px-5 py-4 shrink-0">
            {/* Upload progress */}
            {uploading && (
              <div className="mb-3 bg-blue-50 rounded-xl px-3 py-2.5 flex items-center gap-3">
                <Loader2 className="w-4 h-4 text-blue-500 animate-spin shrink-0" />
                <div className="flex-1">
                  <p className="text-xs font-semibold text-gray-700 mb-1">Uploading…</p>
                  <div className="h-1 bg-gray-200 rounded-full overflow-hidden">
                    <div
                      className="h-full bg-gradient-to-r from-blue-500 to-cyan-400 rounded-full transition-all duration-300"
                      style={{ width: `${uploadPct}%` }}
                    />
                  </div>
                </div>
                <span className="text-xs text-blue-600 font-bold">{uploadPct}%</span>
              </div>
            )}

            <div className="flex flex-col sm:flex-row gap-2">
              <button
                onClick={() => fileRef.current?.click()}
                disabled={uploading}
                className="flex-1 flex items-center justify-center gap-2 px-4 py-2.5 bg-gradient-to-r from-blue-600 to-cyan-500 text-white text-sm font-black rounded-2xl hover:opacity-90 transition-all shadow-md disabled:opacity-50"
              >
                <Upload className="w-4 h-4 shrink-0" />
                Upload Images
              </button>
              <button
                onClick={() => setPickerOpen(true)}
                disabled={uploading}
                className="flex-1 flex items-center justify-center gap-2 px-4 py-2.5 bg-white border-2 border-gray-200 text-gray-700 text-sm font-black rounded-2xl hover:border-violet-400 hover:text-violet-700 transition-all disabled:opacity-50"
              >
                <Library className="w-4 h-4 shrink-0" />
                Media Library
              </button>
            </div>
          </div>
        </div>
      </div>

      <input
        ref={fileRef}
        type="file"
        accept=".jpg,.jpeg,.png,.webp"
        multiple
        className="sr-only"
        onChange={handleFileChange}
      />
    </>
  );
}
