"use client";

import { useRef, useState } from "react";
import { ImagePlus, Loader2, Trash2, Upload } from "lucide-react";
import { useToast } from "@/context/toast-context";
import { cn } from "@/lib/cn";

type Props = {
  images: string[];
  onChange: (images: string[]) => void;
  folder?: string;
  max?: number;
  label?: string;
  single?: boolean;
};

/** Drag-and-drop image uploader that stores files under /public/uploads. */
export function MediaUploader({
  images,
  onChange,
  folder = "products",
  max = 8,
  label = "Product photos",
  single = false,
}: Props) {
  const inputRef = useRef<HTMLInputElement>(null);
  const { toast } = useToast();
  const [uploading, setUploading] = useState(false);
  const [dragOver, setDragOver] = useState(false);

  const uploadFiles = async (files: FileList | File[]) => {
    const list = Array.from(files);
    if (!list.length) return;
    const room = single ? 1 : Math.max(0, max - images.length);
    if (room <= 0) {
      toast(`Maximum ${max} images`, "error");
      return;
    }

    setUploading(true);
    const next = single ? [] : [...images];
    try {
      for (const file of list.slice(0, room)) {
        const body = new FormData();
        body.append("file", file);
        body.append("folder", folder);
        const res = await fetch("/api/admin/upload", {
          method: "POST",
          body,
          credentials: "include",
        });
        const data = (await res.json()) as { url?: string; error?: string };
        if (!res.ok || !data.url) {
          toast(data.error ?? `Failed to upload ${file.name}`, "error");
          continue;
        }
        if (single) next.splice(0, next.length, data.url);
        else next.push(data.url);
      }
      onChange(next);
      if (next.length) toast("Image uploaded");
    } finally {
      setUploading(false);
      if (inputRef.current) inputRef.current.value = "";
    }
  };

  return (
    <div className="space-y-3">
      <div className="flex items-center justify-between gap-3">
        <p className="text-sm font-medium text-foreground">{label}</p>
        <p className="text-xs text-muted">
          {images.length}/{single ? 1 : max} · max 5MB
        </p>
      </div>

      <div
        onDragOver={(event) => {
          event.preventDefault();
          setDragOver(true);
        }}
        onDragLeave={() => setDragOver(false)}
        onDrop={(event) => {
          event.preventDefault();
          setDragOver(false);
          void uploadFiles(event.dataTransfer.files);
        }}
        className={cn(
          "rounded-2xl border border-dashed px-4 py-8 text-center transition",
          dragOver
            ? "border-emerald-400/70 bg-emerald-400/5"
            : "border-border bg-surface",
        )}
      >
        <input
          ref={inputRef}
          type="file"
          accept="image/jpeg,image/png,image/webp,image/gif,image/svg+xml,.ico"
          multiple={!single}
          className="hidden"
          onChange={(event) => {
            if (event.target.files) void uploadFiles(event.target.files);
          }}
        />
        <ImagePlus className="mx-auto h-8 w-8 text-muted" />
        <p className="mt-3 text-sm text-foreground">
          Drag & drop images here, or{" "}
          <button
            type="button"
            onClick={() => inputRef.current?.click()}
            className="font-medium text-emerald-700 hover:underline dark:text-emerald-300"
            disabled={uploading}
          >
            browse files
          </button>
        </p>
        <p className="mt-1 text-xs text-muted">
          Stored on this site under /uploads/{folder}
        </p>
        {uploading ? (
          <p className="mt-3 inline-flex items-center gap-2 text-xs text-muted">
            <Loader2 className="h-3.5 w-3.5 animate-spin" />
            Uploading…
          </p>
        ) : null}
      </div>

      {images.length > 0 ? (
        <ul className="grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4">
          {images.map((src, index) => (
            <li
              key={`${src}-${index}`}
              className="group relative overflow-hidden rounded-xl border border-border bg-surface"
            >
              {/* eslint-disable-next-line @next/next/no-img-element */}
              <img
                src={src}
                alt=""
                className="aspect-square w-full object-cover"
              />
              <div className="absolute inset-x-0 bottom-0 flex items-center justify-between gap-1 bg-gradient-to-t from-black/80 to-transparent p-2">
                <span className="text-[10px] font-medium text-white">
                  {index === 0 ? "Cover" : `#${index + 1}`}
                </span>
                <button
                  type="button"
                  onClick={() => onChange(images.filter((_, i) => i !== index))}
                  className="rounded-md bg-black/50 p-1.5 text-white hover:bg-red-600"
                  aria-label="Remove image"
                >
                  <Trash2 className="h-3.5 w-3.5" />
                </button>
              </div>
              {index > 0 ? (
                <button
                  type="button"
                  onClick={() => {
                    const copy = [...images];
                    const [item] = copy.splice(index, 1);
                    copy.unshift(item);
                    onChange(copy);
                  }}
                  className="absolute left-2 top-2 rounded-md bg-black/55 px-2 py-1 text-[10px] font-medium text-white opacity-0 transition group-hover:opacity-100"
                >
                  Set cover
                </button>
              ) : null}
            </li>
          ))}
        </ul>
      ) : null}

      <button
        type="button"
        onClick={() => inputRef.current?.click()}
        disabled={uploading}
        className="inline-flex h-10 items-center gap-2 rounded-xl border border-border bg-surface px-3 text-sm text-foreground hover:bg-background disabled:opacity-50"
      >
        <Upload className="h-4 w-4" />
        Upload images
      </button>
    </div>
  );
}
