"use client";

import { useRef, useState, useTransition, type ChangeEvent } from "react";
import { clsx } from "clsx";
import {
  ImagePlus,
  Loader2,
  Link as LinkIcon,
  X,
  Check,
  AlertCircle,
} from "lucide-react";
import { uploadAdminImage } from "@/app/admin/uploads/actions";

type Props = {
  /** Hidden form field name — the final image URL is stored here. */
  name: string;
  /** Starting image URL (set when editing an existing record). */
  defaultValue?: string | null;
  /** Bucket on disk — e.g. "blog", "team", "store", "academy", "research". */
  folder?: string;
  /** Label shown above the field. */
  label?: string;
  /** Optional alt-text field name (second hidden input). */
  altName?: string;
  defaultAlt?: string | null;
  required?: boolean;
};

/**
 * Image uploader with three entry points:
 *   1. Click or drag-and-drop a file → uploads via the `uploadAdminImage`
 *      server action → sets the final URL into a hidden input so the parent
 *      <form> posts it with the normal submit.
 *   2. Paste/type a URL manually — still supported for legacy /photos paths.
 *   3. Current image preview + clear button for re-upload.
 */
export function ImageUpload({
  name,
  defaultValue,
  folder = "misc",
  label = "Image",
  altName,
  defaultAlt,
  required,
}: Props) {
  const [url, setUrl] = useState<string>(defaultValue ?? "");
  const [alt, setAlt] = useState<string>(defaultAlt ?? "");
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState<boolean>(false);
  const [dragging, setDragging] = useState<boolean>(false);
  const [pending, startTransition] = useTransition();
  const fileInputRef = useRef<HTMLInputElement>(null);

  function handleFiles(files: FileList | null) {
    const file = files?.[0];
    if (!file) return;
    setError(null);
    setSuccess(false);

    const fd = new FormData();
    fd.set("file", file);
    fd.set("folder", folder);

    startTransition(async () => {
      const result = await uploadAdminImage(fd);
      if (!result.ok) {
        setError(result.error);
        return;
      }
      setUrl(result.url);
      setSuccess(true);
      // Clear the success state after a moment
      setTimeout(() => setSuccess(false), 2500);
    });
  }

  function onFileChange(e: ChangeEvent<HTMLInputElement>) {
    handleFiles(e.target.files);
    if (fileInputRef.current) fileInputRef.current.value = "";
  }

  function onUrlChange(e: ChangeEvent<HTMLInputElement>) {
    setUrl(e.target.value);
    setSuccess(false);
  }

  function onClear() {
    setUrl("");
    setError(null);
    setSuccess(false);
  }

  const hasImage = Boolean(url);

  return (
    <div className="flex flex-col gap-2">
      <label className="text-[11px] font-bold uppercase tracking-wider text-[var(--color-slate)]">
        {label}
        {required && <span className="ml-1 text-[var(--color-blue)]">*</span>}
      </label>

      {/* Drop zone / preview card */}
      <div
        className={clsx(
          "relative flex flex-col gap-3 rounded-xl border-2 border-dashed bg-white p-4 transition-colors",
          dragging
            ? "border-[var(--color-blue)] bg-[var(--color-mist)]/40"
            : "border-[var(--color-line)]",
          error && "border-red-300 bg-red-50/40",
        )}
        onDragOver={(e) => {
          e.preventDefault();
          setDragging(true);
        }}
        onDragLeave={() => setDragging(false)}
        onDrop={(e) => {
          e.preventDefault();
          setDragging(false);
          handleFiles(e.dataTransfer.files);
        }}
      >
        <div className="flex items-start gap-4">
          {hasImage ? (
            /* eslint-disable-next-line @next/next/no-img-element */
            <img
              src={url}
              alt={alt || ""}
              className="h-24 w-24 flex-none rounded-md object-cover ring-1 ring-[var(--color-line)]"
              onError={() => setError("Image failed to load at that URL")}
            />
          ) : (
            <div className="flex h-24 w-24 flex-none items-center justify-center rounded-md bg-[var(--color-mist)]/60 text-[var(--color-blue)] ring-1 ring-[var(--color-line)]">
              <ImagePlus className="h-8 w-8" aria-hidden />
            </div>
          )}

          <div className="flex min-w-0 flex-1 flex-col gap-2">
            <div className="flex flex-wrap items-center gap-2">
              <button
                type="button"
                onClick={() => fileInputRef.current?.click()}
                disabled={pending}
                className="inline-flex items-center gap-2 rounded-lg bg-[var(--color-blue)] px-3 py-1.5 text-[13px] font-semibold text-white transition-colors hover:bg-[var(--color-blue-deep)] disabled:opacity-60"
              >
                {pending ? (
                  <>
                    <Loader2 className="h-4 w-4 animate-spin" aria-hidden />
                    Uploading…
                  </>
                ) : (
                  <>
                    <ImagePlus className="h-4 w-4" aria-hidden />
                    {hasImage ? "Replace image" : "Upload image"}
                  </>
                )}
              </button>
              {hasImage && (
                <button
                  type="button"
                  onClick={onClear}
                  className="inline-flex items-center gap-1.5 rounded-lg border border-[var(--color-line)] bg-white px-3 py-1.5 text-[13px] font-semibold text-[var(--color-ink)] hover:border-[var(--color-blue)] hover:text-[var(--color-blue)]"
                >
                  <X className="h-3.5 w-3.5" aria-hidden />
                  Clear
                </button>
              )}
            </div>
            <p className="text-[12px] text-[var(--color-slate)]">
              Drag & drop or click to upload. JPG, PNG, WebP, GIF, or SVG. Max 8 MB.
            </p>
          </div>
        </div>

        {/* URL pass-through for legacy /photos paths */}
        <div className="flex flex-wrap items-center gap-2">
          <span className="flex items-center gap-1.5 text-[11px] font-bold uppercase tracking-wider text-[var(--color-slate)]">
            <LinkIcon className="h-3 w-3" aria-hidden />
            Or URL
          </span>
          <input
            type="text"
            value={url}
            onChange={onUrlChange}
            placeholder="/photos/category/file.jpg"
            className="flex-1 min-w-[220px] rounded-md border border-[var(--color-line)] bg-white px-3 py-1.5 text-[13px] text-[var(--color-ink)] placeholder:text-[var(--color-slate)]/70 focus:border-[var(--color-blue)] focus:outline-none focus:ring-2 focus:ring-[var(--color-mist)]"
          />
        </div>

        <input
          ref={fileInputRef}
          type="file"
          accept="image/jpeg,image/png,image/webp,image/gif,image/svg+xml"
          onChange={onFileChange}
          className="hidden"
        />
        {/* The actual hidden value the parent <form> submits */}
        <input type="hidden" name={name} value={url} />
        {altName && (
          <div className="flex flex-col gap-1">
            <label className="text-[11px] font-bold uppercase tracking-wider text-[var(--color-slate)]">
              Alt text
            </label>
            <input
              type="text"
              name={altName}
              value={alt}
              onChange={(e) => setAlt(e.target.value)}
              placeholder="Describe the image for screen readers"
              className="rounded-md border border-[var(--color-line)] bg-white px-3 py-1.5 text-[13px] text-[var(--color-ink)] placeholder:text-[var(--color-slate)]/70 focus:border-[var(--color-blue)] focus:outline-none focus:ring-2 focus:ring-[var(--color-mist)]"
            />
          </div>
        )}
      </div>

      {/* Status rail */}
      <div className="min-h-[18px] text-[12px]">
        {error && (
          <span className="inline-flex items-center gap-1.5 font-semibold text-red-600">
            <AlertCircle className="h-3.5 w-3.5" aria-hidden />
            {error}
          </span>
        )}
        {success && !error && (
          <span className="inline-flex items-center gap-1.5 font-semibold text-emerald-700">
            <Check className="h-3.5 w-3.5" aria-hidden />
            Uploaded — saved to {url}
          </span>
        )}
      </div>
    </div>
  );
}
