"use client";

/**
 * BrandBulkUpload — upload 50+ images at once, then assign each to a specific car.
 *
 * Flow:
 *  1. Admin selects a brand
 *  2. Admin drops/selects multiple image files
 *  3. Files are uploaded to the media library (category="car")
 *  4. Each uploaded image appears in a list with a car-dropdown
 *  5. Admin selects which car each image belongs to
 *  6. "Assign All" bulk-assigns via POST /api/car-images/bulk-assign
 */

import { useCallback, useEffect, useRef, useState } from "react";
import Image from "next/image";
import {
  Upload, X, CheckCircle2, AlertCircle, Loader2,
  ChevronDown, Car, Package, Crown,
} from "lucide-react";
import { cn } from "@/lib/utils";
import { getAdminToken } from "@/lib/adminAuth";
import { resolveUploadUrl } from "@/lib/uploadUrl";

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

interface CarStub { carId: string; name: string }

interface UploadedItem {
  id:           string;   // local queue id
  file:         File;
  status:       "pending" | "uploading" | "done" | "error";
  progress:     number;
  mediaId?:     string;   // populated after upload
  thumbnailUrl?: string;
  error?:       string;
  assignedCarId?: string;
  setAsPrimary:   boolean;
}

interface Props {
  open:     boolean;
  onClose:  () => void;
  onDone:   () => void;   // refresh parent
}

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) { const d = await res.json().catch(() => ({})); throw new Error(d.detail ?? `HTTP ${res.status}`); }
  return res.json();
}

const BRANDS = [
  "Maruti Suzuki", "Hyundai", "Tata", "Mahindra", "Kia",
  "Toyota", "Honda", "MG", "Skoda", "Volkswagen",
  "BMW", "Mercedes-Benz", "Audi", "Lexus", "Volvo",
];

function fmtBytes(n: number) {
  if (n < 1024) return `${n} B`;
  if (n < 1048576) return `${(n / 1024).toFixed(1)} KB`;
  return `${(n / 1048576).toFixed(2)} MB`;
}

export default function BrandBulkUpload({ open, onClose, onDone }: Props) {
  const [brand,       setBrand]       = useState<string>("");
  const [cars,        setCars]        = useState<CarStub[]>([]);
  const [carsLoading, setCarsLoading] = useState(false);
  const [queue,       setQueue]       = useState<UploadedItem[]>([]);
  const [dragging,    setDragging]    = useState(false);
  const [assigning,   setAssigning]   = useState(false);
  const [toast,       setToast]       = useState<{ msg: string; ok: boolean } | null>(null);
  const fileRef = useRef<HTMLInputElement>(null);

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

  // Load cars for selected brand
  useEffect(() => {
    if (!brand) { setCars([]); return; }
    setCarsLoading(true);
    const token = getAdminToken();
    fetch(`${API}/api/car-images/cars?brand=${encodeURIComponent(brand)}&limit=100`, {
      headers: token ? { Authorization: `Bearer ${token}` } : {},
    })
      .then((r) => r.json())
      .then((d) => setCars((d.cars ?? []).map((c: any) => ({ carId: c.carId, name: c.name }))))
      .catch(() => setCars([]))
      .finally(() => setCarsLoading(false));
  }, [brand]);

  // Reset queue when modal is closed
  useEffect(() => {
    if (!open) { setQueue([]); setBrand(""); setCars([]); }
  }, [open]);

  // Upload one file → media library
  const uploadFile = useCallback(async (item: UploadedItem) => {
    setQueue((q) => q.map((i) => i.id === item.id ? { ...i, status: "uploading", progress: 0 } : i));
    const token = getAdminToken();
    const fd    = new FormData();
    fd.append("file", item.file);

    return new Promise<void>((resolve) => {
      const xhr = new XMLHttpRequest();
      xhr.open("POST", `${API}/api/upload/image?category=car`);
      if (token) xhr.setRequestHeader("Authorization", `Bearer ${token}`);
      xhr.upload.onprogress = (e) => {
        if (e.lengthComputable) {
          const pct = Math.round((e.loaded / e.total) * 90);
          setQueue((q) => q.map((i) => i.id === item.id ? { ...i, progress: pct } : i));
        }
      };
      xhr.onload = () => {
        if (xhr.status >= 200 && xhr.status < 300) {
          const r = JSON.parse(xhr.responseText);
          setQueue((q) => q.map((i) => i.id === item.id ? {
            ...i, status: "done", progress: 100,
            mediaId: r.id, thumbnailUrl: r.thumbnailUrl,
          } : i));
        } else {
          let msg = `HTTP ${xhr.status}`;
          try { msg = JSON.parse(xhr.responseText).detail ?? msg; } catch {}
          setQueue((q) => q.map((i) => i.id === item.id ? { ...i, status: "error", error: msg } : i));
        }
        resolve();
      };
      xhr.onerror = () => {
        setQueue((q) => q.map((i) => i.id === item.id ? { ...i, status: "error", error: "Network error" } : i));
        resolve();
      };
      xhr.send(fd);
    });
  }, []);

  // Add files to queue and start uploading
  const addFiles = useCallback(async (files: File[]) => {
    const newItems: UploadedItem[] = files.map((f) => ({
      id:           `${Date.now()}-${Math.random().toString(36).slice(2)}`,
      file:         f,
      status:       "pending",
      progress:     0,
      setAsPrimary: false,
    }));
    setQueue((q) => [...q, ...newItems]);

    // Upload in batches of 3
    for (let i = 0; i < newItems.length; i += 3) {
      await Promise.all(newItems.slice(i, i + 3).map(uploadFile));
    }
  }, [uploadFile]);

  const onDrop = (e: React.DragEvent) => {
    e.preventDefault(); setDragging(false);
    addFiles(Array.from(e.dataTransfer.files));
  };
  const onFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    addFiles(Array.from(e.target.files ?? []));
    e.target.value = "";
  };

  function setAssignedCar(queueId: string, carId: string) {
    setQueue((q) => q.map((i) => i.id === queueId ? { ...i, assignedCarId: carId } : i));
  }

  function togglePrimary(queueId: string) {
    setQueue((q) => q.map((i) => i.id === queueId ? { ...i, setAsPrimary: !i.setAsPrimary } : i));
  }

  function removeItem(queueId: string) {
    setQueue((q) => q.filter((i) => i.id !== queueId));
  }

  const assigned = queue.filter((i) => i.status === "done" && i.assignedCarId && i.mediaId);

  async function assignAll() {
    if (!assigned.length) { showToast("No images ready to assign", false); return; }
    setAssigning(true);
    try {
      const assignments = assigned.map((i) => ({
        mediaId:      i.mediaId!,
        carId:        i.assignedCarId!,
        setAsPrimary: i.setAsPrimary,
      }));
      const result = await apiFetch("/api/car-images/bulk-assign", {
        method: "POST",
        body:   JSON.stringify({ assignments }),
      });
      showToast(`${result.assigned} image${result.assigned !== 1 ? "s" : ""} assigned successfully`);
      // Clear assigned items from queue
      setQueue((q) => q.filter((i) => !i.assignedCarId || !i.mediaId));
      onDone();
    } catch (e: any) {
      showToast(e.message, false);
    } finally {
      setAssigning(false);
    }
  }

  if (!open) return null;

  const doneCount     = queue.filter((i) => i.status === "done").length;
  const uploadingCount= queue.filter((i) => i.status === "uploading").length;
  const errorCount    = queue.filter((i) => i.status === "error").length;

  return (
    <div
      className="fixed inset-0 z-[150] 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-3xl max-h-[90vh] flex flex-col overflow-hidden"
        onClick={(e) => e.stopPropagation()}
      >
        {/* Header */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-gray-100 shrink-0">
          <div className="flex items-center gap-3">
            <div className="w-9 h-9 bg-gradient-to-br from-orange-500 to-amber-400 rounded-xl flex items-center justify-center shadow">
              <Package className="w-4 h-4 text-white" />
            </div>
            <div>
              <h2 className="text-sm font-black text-gray-900">Bulk Upload by Brand</h2>
              <p className="text-xs text-gray-400">Upload many images → assign to individual cars</p>
            </div>
          </div>
          <button onClick={onClose} className="p-2 rounded-xl hover:bg-gray-100 transition-colors">
            <X className="w-5 h-5 text-gray-400" />
          </button>
        </div>

        {/* Toast */}
        {toast && (
          <div className={cn(
            "mx-5 mt-3 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>
        )}

        <div className="flex-1 overflow-y-auto p-5 space-y-5">
          {/* Brand selector */}
          <div>
            <label className="text-xs font-black text-gray-600 block mb-2">
              Select Brand <span className="text-red-500">*</span>
            </label>
            <div className="relative">
              <select
                value={brand}
                onChange={(e) => setBrand(e.target.value)}
                className="w-full appearance-none bg-white border-2 border-gray-200 rounded-2xl px-4 py-2.5 text-sm font-semibold text-gray-800 focus:outline-none focus:border-blue-400 pr-10"
              >
                <option value="">— Choose a brand —</option>
                {BRANDS.map((b) => <option key={b} value={b}>{b}</option>)}
              </select>
              <ChevronDown className="absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400 pointer-events-none" />
            </div>
          </div>

          {/* Drop zone */}
          <div>
            <label className="text-xs font-black text-gray-600 block mb-2">
              Drop Images
              {doneCount > 0 && (
                <span className="ml-2 text-green-600">
                  {doneCount} uploaded{uploadingCount > 0 ? `, ${uploadingCount} uploading` : ""}
                  {errorCount > 0 ? `, ${errorCount} failed` : ""}
                </span>
              )}
            </label>
            <div
              onDragOver={(e) => { e.preventDefault(); setDragging(true); }}
              onDragLeave={() => setDragging(false)}
              onDrop={onDrop}
              onClick={() => fileRef.current?.click()}
              className={cn(
                "border-2 border-dashed rounded-2xl flex flex-col items-center justify-center gap-2 py-8 cursor-pointer transition-all",
                dragging ? "border-blue-400 bg-blue-50 scale-[1.01]"
                         : "border-gray-200 bg-gray-50 hover:border-blue-300 hover:bg-blue-50/30"
              )}
            >
              <Upload className={cn("w-7 h-7", dragging ? "text-blue-500" : "text-gray-300")} />
              <p className="text-sm font-bold text-gray-600">
                {dragging ? "Drop to upload" : "Drag & drop images or click to browse"}
              </p>
              <p className="text-xs text-gray-400">JPG, PNG, WebP · Max 10 MB each · No limit on file count</p>
            </div>
          </div>

          {/* Queue with assignment dropdowns */}
          {queue.length > 0 && (
            <div>
              <div className="flex items-center justify-between mb-2">
                <label className="text-xs font-black text-gray-600">
                  Assign to Cars
                </label>
                {carsLoading && <Loader2 className="w-3.5 h-3.5 text-gray-400 animate-spin" />}
                {!brand && <span className="text-[10px] text-amber-600 font-semibold">← Select a brand first</span>}
              </div>

              <div className="space-y-2 max-h-60 overflow-y-auto pr-1">
                {queue.map((item) => (
                  <div
                    key={item.id}
                    className="flex flex-wrap items-center gap-x-3 gap-y-2 bg-white border border-gray-100 rounded-xl px-3 py-2 shadow-sm"
                  >
                    {/* Thumbnail */}
                    <div className="w-10 h-10 rounded-lg bg-gray-100 overflow-hidden shrink-0 relative">
                      {item.thumbnailUrl ? (
                        <Image src={resolveUploadUrl(item.thumbnailUrl)} alt={item.file.name} fill className="object-cover" unoptimized sizes="40px" />
                      ) : (
                        <div className="w-full h-full flex items-center justify-center">
                          {item.status === "uploading" ? (
                            <Loader2 className="w-4 h-4 text-blue-400 animate-spin" />
                          ) : item.status === "error" ? (
                            <AlertCircle className="w-4 h-4 text-red-400" />
                          ) : (
                            <Car className="w-4 h-4 text-gray-300" />
                          )}
                        </div>
                      )}
                    </div>

                    {/* File info */}
                    <div className="flex-1 min-w-0">
                      <p className="text-xs font-semibold text-gray-700 truncate">{item.file.name}</p>
                      {item.status === "uploading" && (
                        <div className="mt-1 h-1 bg-gray-100 rounded-full overflow-hidden">
                          <div className="h-full bg-blue-500 rounded-full transition-all" style={{ width: `${item.progress}%` }} />
                        </div>
                      )}
                      {item.status === "error" && <p className="text-[10px] text-red-500">{item.error}</p>}
                      {item.status === "done" && <p className="text-[10px] text-gray-400">{fmtBytes(item.file.size)}</p>}
                    </div>

                    {/* Car assignment dropdown */}
                    {item.status === "done" && (
                      <div className="flex items-center gap-1.5 w-full sm:w-auto sm:shrink-0 min-w-0">
                        <button
                          onClick={() => togglePrimary(item.id)}
                          title={item.setAsPrimary ? "Will set as primary" : "Set as primary"}
                          className={cn(
                            "p-1.5 rounded-lg transition-colors shrink-0",
                            item.setAsPrimary ? "text-amber-500 bg-amber-50" : "text-gray-300 hover:text-amber-400"
                          )}
                        >
                          <Crown className="w-3.5 h-3.5" />
                        </button>

                        <select
                          value={item.assignedCarId ?? ""}
                          onChange={(e) => setAssignedCar(item.id, e.target.value)}
                          disabled={!brand || carsLoading}
                          className="flex-1 sm:flex-none text-xs border border-gray-200 rounded-xl px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-blue-400 sm:max-w-[160px] min-w-0 disabled:opacity-50 font-semibold text-gray-700"
                        >
                          <option value="">— Select car —</option>
                          {cars.map((c) => (
                            <option key={c.carId} value={c.carId}>{c.name}</option>
                          ))}
                        </select>
                      </div>
                    )}

                    {/* Remove */}
                    <button
                      onClick={() => removeItem(item.id)}
                      className="p-1 rounded hover:bg-gray-100 text-gray-300 hover:text-red-500 transition-colors shrink-0"
                    >
                      <X className="w-3.5 h-3.5" />
                    </button>
                  </div>
                ))}
              </div>
            </div>
          )}
        </div>

        {/* Footer */}
        <div className="border-t border-gray-100 px-5 py-4 shrink-0 flex flex-col sm:flex-row sm:items-center justify-between gap-3">
          <p className="text-xs text-gray-400 text-center sm:text-left min-w-0">
            {assigned.length > 0
              ? `${assigned.length} image${assigned.length !== 1 ? "s" : ""} ready to assign`
              : "Upload images and select cars to assign"}
          </p>
          <div className="flex gap-2 justify-center sm:justify-end shrink-0">
            <button
              onClick={onClose}
              className="px-4 py-2 text-sm font-bold text-gray-600 bg-gray-100 hover:bg-gray-200 rounded-xl transition-colors"
            >
              Close
            </button>
            <button
              onClick={assignAll}
              disabled={assigned.length === 0 || assigning}
              className="flex items-center gap-2 px-4 py-2 text-sm font-black text-white bg-gradient-to-r from-orange-500 to-amber-400 rounded-xl hover:opacity-90 transition-all shadow-md disabled:opacity-40 disabled:cursor-not-allowed"
            >
              {assigning ? <Loader2 className="w-4 h-4 animate-spin" /> : <CheckCircle2 className="w-4 h-4" />}
              Assign {assigned.length > 0 ? `${assigned.length} ` : ""}Images
            </button>
          </div>
        </div>
      </div>

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