"use client";

import { startTransition, useActionState, useEffect, useState } from "react";
import { addLabelVersion } from "@/lib/actions/labels";
import { LabelCropTool } from "@/components/labels/LabelCropTool";

export function ReplaceVersionForm({
  labelId,
  minSourceDimension,
}: {
  labelId: string;
  minSourceDimension: number;
}) {
  const [state, formAction, isPending] = useActionState(
    addLabelVersion,
    undefined,
  );
  const [pendingFile, setPendingFile] = useState<File | null>(null);
  const [croppedFile, setCroppedFile] = useState<File | null>(null);
  const [croppedPreviewUrl, setCroppedPreviewUrl] = useState<string | null>(
    null,
  );

  useEffect(() => {
    if (!croppedFile) return;
    const url = URL.createObjectURL(croppedFile);
    // See LabelCropTool.tsx's identical pattern: object URLs are an
    // external resource needing cleanup, and useMemo doesn't survive
    // Strict Mode's double-invoked cleanup here.
    // eslint-disable-next-line react-hooks/set-state-in-effect
    setCroppedPreviewUrl(url);
    return () => URL.revokeObjectURL(url);
  }, [croppedFile]);

  function handleFileChange(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0] ?? null;
    setPendingFile(file);
    setCroppedFile(null);
  }

  function handleCropped(blob: Blob) {
    setCroppedFile(new File([blob], "label.png", { type: "image/png" }));
  }

  function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    if (!croppedFile) return;
    const fd = new FormData(e.currentTarget);
    fd.set("file", croppedFile);
    startTransition(() => {
      formAction(fd);
    });
  }

  return (
    <form onSubmit={handleSubmit} className="flex flex-col gap-3">
      <input type="hidden" name="labelId" value={labelId} />

      {!pendingFile && !croppedFile && (
        <div className="flex flex-wrap items-center gap-3">
          <input
            type="file"
            accept="image/png,image/jpeg"
            required
            onChange={handleFileChange}
            className="rounded border border-charcoal/20 bg-warm-white px-4 py-2 text-charcoal"
          />
        </div>
      )}

      {pendingFile && !croppedFile && (
        <LabelCropTool
          key={`${pendingFile.name}-${pendingFile.size}-${pendingFile.lastModified}`}
          file={pendingFile}
          minSourceDimension={minSourceDimension}
          onCropped={handleCropped}
          onCancel={() => setPendingFile(null)}
        />
      )}

      {croppedFile && croppedPreviewUrl && (
        <div className="flex flex-col items-start gap-2">
          {/* eslint-disable-next-line @next/next/no-img-element */}
          <img
            src={croppedPreviewUrl}
            alt="Cropped label preview"
            className="rounded-full border border-charcoal/20"
            width={160}
            height={160}
          />
          <button
            type="button"
            onClick={() => setCroppedFile(null)}
            className="text-xs font-medium text-terracotta hover:underline"
          >
            Re-crop
          </button>
        </div>
      )}

      <button
        type="submit"
        disabled={isPending || !croppedFile}
        className="w-fit rounded-full bg-terracotta px-5 py-2 text-sm font-medium text-white hover:bg-terracotta/90 disabled:opacity-60"
      >
        {isPending ? "Uploading..." : "Add version"}
      </button>
      {state?.error && (
        <p className="w-full text-sm text-terracotta">{state.error}</p>
      )}
      {state?.success && (
        <p className="w-full text-sm text-charcoal/60">
          New version added.
        </p>
      )}
    </form>
  );
}
