"use client";

import { startTransition, useActionState, useEffect, useState } from "react";
import { uploadLabel } from "@/lib/actions/labels";
import {
  BrandBlendAutocomplete,
  type Suggestion,
} from "@/components/labels/BrandBlendAutocomplete";
import { LabelCropTool } from "@/components/labels/LabelCropTool";

export function UploadForm({
  initialBrand,
  initialBlend,
  minSourceDimension,
}: {
  initialBrand?: Suggestion | null;
  initialBlend?: Suggestion | null;
  minSourceDimension: number;
}) {
  const [state, formAction, isPending] = useActionState(
    uploadLabel,
    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-6">
      <BrandBlendAutocomplete
        initialBrand={initialBrand}
        initialBlend={initialBlend}
      />

      {!pendingFile && !croppedFile && (
        <label className="flex flex-col gap-1">
          <span className="text-sm font-medium text-charcoal">
            Label image
          </span>
          <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"
          />
          <span className="text-xs text-charcoal/60">
            PNG or JPG, at least {minSourceDimension}x{minSourceDimension}px.
            You&apos;ll be able to crop it into a circle next.
          </span>
        </label>
      )}

      {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-center gap-2">
          <span className="text-sm font-medium text-charcoal">Preview</span>
          {/* eslint-disable-next-line @next/next/no-img-element */}
          <img
            src={croppedPreviewUrl}
            alt="Cropped label preview"
            className="rounded-full border border-charcoal/20"
            width={320}
            height={320}
          />
          <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="rounded-full bg-terracotta px-6 py-2 font-medium text-white hover:bg-terracotta/90 disabled:opacity-60"
      >
        {isPending ? "Uploading..." : "Upload Label"}
      </button>

      {state?.error && (
        <p className="rounded bg-terracotta/10 px-4 py-2 text-sm text-terracotta">
          {state.error}
        </p>
      )}
    </form>
  );
}
