import { useRef } from "react";
import Image from "next/image";
import { ImagePlus, Link2, Undo2, X } from "lucide-react";
import type { UseFormReturn } from "react-hook-form";
import type { ApiSavedImage } from "@/lib/api/types";
import { type ProductFormValues } from "./product.schema";
import { Field, SectionCard, inputClass } from "./fields";

const MAX_IMAGES = 5;
const MAX_SIZE = 5 * 1024 * 1024; // 5MB

type Props = { form: UseFormReturn<ProductFormValues>; existingImages?: ApiSavedImage[] };

export default function Step2Media({ form, existingImages = [] }: Props) {
  const {
    register,
    watch,
    setValue,
    formState: { errors },
  } = form;
  const inputRef = useRef<HTMLInputElement>(null);

  const images = (watch("product_images") as File[]) ?? [];
  const removed = watch("removed_images") ?? [];

  const kept = existingImages.filter((image) => !removed.includes(String(image.id)));
  /* Five is the ceiling across both lists, so newly picked files have to leave
     room for the saved ones the seller is keeping. */
  const slotsLeft = Math.max(0, MAX_IMAGES - kept.length);

  const addFiles = (fileList: FileList | null) => {
    if (!fileList) return;
    const incoming = Array.from(fileList).filter((file) => {
      if (!file.type.startsWith("image/")) return false;
      if (file.size > MAX_SIZE) return false;
      return true;
    });
    const next = [...images, ...incoming].slice(0, slotsLeft);
    setValue("product_images", next, { shouldValidate: true, shouldDirty: true, shouldTouch: true });
  };

  const removeImage = (index: number) => {
    const next = images.filter((_, i) => i !== index);
    setValue("product_images", next, { shouldValidate: true, shouldDirty: true });
  };

  /* Removing a saved image only marks it. Nothing leaves the listing until the
     step is saved, which is what makes Undo possible and keeps a mis-click from
     costing an image. */
  const removeSaved = (id: number) =>
    setValue("removed_images", [...removed, String(id)], { shouldDirty: true });

  const restoreSaved = () => {
    setValue("removed_images", [], { shouldDirty: true });
    // Dropping back over the limit is possible after a restore; trim the queue.
    const room = Math.max(0, MAX_IMAGES - existingImages.length);
    if (images.length > room) {
      setValue("product_images", images.slice(0, room), { shouldValidate: true, shouldDirty: true });
    }
  };

  const slots = Array.from({ length: Math.max(slotsLeft, 1) });

  return (
    <SectionCard title="Media Upload">
      <div className="space-y-4">
        <Field label="Product Images" required error={errors.product_images?.message as string | undefined}>
          <div
            role="button"
            tabIndex={0}
            onClick={() => inputRef.current?.click()}
            onKeyDown={(e) => {
              if (e.key === "Enter" || e.key === " ") inputRef.current?.click();
            }}
            onDragOver={(e) => e.preventDefault()}
            onDrop={(e) => {
              e.preventDefault();
              addFiles(e.dataTransfer.files);
            }}
            className="flex cursor-pointer flex-col items-center justify-center rounded-xl border-2 border-dashed border-gray-200 bg-gray-50/60 px-4 py-8 text-center transition hover:border-[#CC1414]"
          >
            <ImagePlus className="mb-2 h-8 w-8 text-gray-400" />
            <p className="text-sm font-medium text-gray-700">Upload Images</p>
            <p className="mt-1 text-xs text-gray-500">Drag &amp; drop or click to upload</p>
            <p className="text-xs text-gray-400">JPG, PNG (Max. 5MB each)</p>
          </div>
          <input
            ref={inputRef}
            type="file"
            accept="image/*"
            multiple
            className="hidden"
            onChange={(e) => {
              addFiles(e.target.files);
              e.target.value = "";
            }}
          />
        </Field>

        <Field label="Product Video" error={errors.product_video?.message}>
          <div className="relative">
            <input
              {...register("product_video")}
              className={`${inputClass} pr-9`}
              placeholder="Enter video URL (YouTube/Vimeo)"
            />
            <Link2 className="pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400" />
          </div>
        </Field>

        {existingImages.length > 0 && (
          <div>
            <p className="mb-2 text-xs font-medium text-gray-700">Uploaded images</p>

            {kept.length === 0 ? (
              <p className="rounded-lg border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800">
                Every saved image is marked for removal. Upload a replacement or undo — a listing
                cannot be saved without an image.
              </p>
            ) : (
              <div className="grid grid-cols-2 gap-3 sm:grid-cols-4 lg:grid-cols-5">
                {kept.map((image) => (
                  <div
                    key={image.id}
                    className="group relative flex aspect-square items-center justify-center overflow-hidden rounded-lg border border-gray-200 bg-gray-50"
                  >
                    {/* eslint-disable-next-line @next/next/no-img-element */}
                    <img src={image.url} alt="Saved product" className="h-full w-full object-cover" />
                    <button
                      type="button"
                      onClick={() => removeSaved(image.id)}
                      className="absolute right-1 top-1 rounded-full bg-black/60 p-1 text-white hover:bg-black/80"
                      aria-label="Remove this image"
                    >
                      <X className="h-3 w-3" />
                    </button>
                  </div>
                ))}
              </div>
            )}

            {removed.length > 0 ? (
              <div className="mt-2 flex flex-wrap items-center gap-2 text-xs text-gray-600">
                <span>
                  {removed.length} image{removed.length > 1 ? "s" : ""} will be removed when you save
                  this step.
                </span>
                <button
                  type="button"
                  onClick={restoreSaved}
                  className="inline-flex items-center gap-1 rounded-md border border-gray-200 px-2 py-1 font-medium text-gray-700 hover:bg-gray-50"
                >
                  <Undo2 className="h-3 w-3" /> Undo
                </button>
              </div>
            ) : (
              <p className="mt-1 text-xs text-gray-400">
                These are already saved. Add more below to append, or remove one with ✕.
              </p>
            )}
          </div>
        )}

        <div>
          <div className="grid grid-cols-2 gap-3 sm:grid-cols-4 lg:grid-cols-5">
            {slots.map((_, index) => {
              const file = images[index];
              return (
                <div
                  key={index}
                  className="relative flex aspect-square items-center justify-center overflow-hidden rounded-lg border border-gray-200 bg-gray-50"
                >
                  {file ? (
                    <>
                      <Image
                        src={URL.createObjectURL(file)}
                        alt={`Product image ${index + 1}`}
                        fill
                        sizes="120px"
                        className="object-cover"
                        unoptimized
                      />
                      <button
                        type="button"
                        onClick={() => removeImage(index)}
                        className="absolute right-1 top-1 rounded-full bg-black/60 p-1 text-white hover:bg-black/80"
                        aria-label="Remove image"
                      >
                        <X className="h-3 w-3" />
                      </button>
                    </>
                  ) : (
                    <ImagePlus className="h-6 w-6 text-gray-300" />
                  )}
                </div>
              );
            })}
          </div>
          <p className="mt-2 text-xs text-gray-500">
            {slotsLeft > 0
              ? `You can add ${slotsLeft} more image${slotsLeft > 1 ? "s" : ""} (${MAX_IMAGES} in total).`
              : `You already have ${MAX_IMAGES} images. Remove one to add another.`}
          </p>
        </div>
      </div>
    </SectionCard>
  );
}
