"use client";

import { useRef, useState } from "react";
import { ImagePlus, Link2, Loader2, Trash2, Upload } from "lucide-react";
import { useTranslations } from "next-intl";
import Button from "@/components/ui/Button";
import { toastPromise } from "@/lib/toast";

interface ImagePickerProps {
  label: string;
  hint?: string;
  value: string;
  disabled?: boolean;
  compact?: boolean;
  uploadUrl?: string;
  onChange: (url: string) => void;
}

export default function ImagePicker({
  label,
  hint,
  value,
  disabled,
  compact,
  uploadUrl = "/api/businesses/upload",
  onChange,
}: ImagePickerProps) {
  const t = useTranslations("branding");
  const inputRef = useRef<HTMLInputElement>(null);
  const [uploading, setUploading] = useState(false);
  const [dragOver, setDragOver] = useState(false);
  const [showUrl, setShowUrl] = useState(Boolean(value && /^https?:\/\//i.test(value)));

  async function handleFile(file: File | undefined) {
    if (!file || disabled) return;
    setUploading(true);

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

    try {
      const data = await toastPromise(
        (async () => {
          const res = await fetch(uploadUrl, { method: "POST", body });
          const json = await res.json().catch(() => ({}));
          if (!res.ok) {
            throw new Error(
              typeof json.error === "string" ? json.error : t("uploadFailed")
            );
          }
          if (typeof json.url !== "string") {
            throw new Error(t("uploadFailed"));
          }
          onChange(json.url);
          setShowUrl(false);
          return json;
        })(),
        {
          loading: t("uploading"),
          success: t("uploadSuccess"),
          error: (err) =>
            err instanceof Error ? err.message : t("uploadFailed"),
        }
      );
      void data;
    } catch {
      // surfaced via toast
    } finally {
      setUploading(false);
      if (inputRef.current) inputRef.current.value = "";
    }
  }

  function onDrop(e: React.DragEvent) {
    e.preventDefault();
    setDragOver(false);
    if (disabled || uploading) return;
    const file = e.dataTransfer.files?.[0];
    if (file) handleFile(file);
  }

  const previewSize = compact ? "h-20 w-20" : "h-24 w-24";
  const dropPadding = compact ? "px-3 py-5" : "px-4 py-8";

  return (
    <div className="space-y-3">
      <div className="flex items-start justify-between gap-3">
        <div>
          <p className="text-sm font-medium text-[var(--text)]">{label}</p>
          <p className="mt-0.5 text-xs text-[var(--text-faint)]">{hint ?? t("imageHint")}</p>
        </div>
        {value && (
          <Button
            type="button"
            variant="ghost"
            size="sm"
            disabled={disabled || uploading}
            onClick={() => onChange("")}
          >
            <Trash2 className="h-3.5 w-3.5" />
            {t("removeImage")}
          </Button>
        )}
      </div>

      <div
        onDragOver={(e) => {
          e.preventDefault();
          if (!disabled && !uploading) setDragOver(true);
        }}
        onDragLeave={() => setDragOver(false)}
        onDrop={onDrop}
        className={`relative flex flex-col items-center justify-center rounded-xl border border-dashed ${dropPadding} transition-colors ${
          dragOver
            ? "border-[var(--accent)] bg-[var(--accent-muted)]"
            : "border-[var(--border)] bg-[var(--bg)] hover:border-[var(--accent)]/40"
        } ${disabled ? "opacity-60" : ""}`}
      >
        <button
          type="button"
          disabled={disabled || uploading}
          onClick={() => inputRef.current?.click()}
          className="flex cursor-pointer flex-col items-center gap-2.5 disabled:cursor-not-allowed"
          aria-label={t("chooseImage")}
        >
          <div
            className={`relative flex ${previewSize} items-center justify-center overflow-hidden rounded-2xl border border-[var(--border)] bg-[var(--bg-elevated)]`}
          >
            {value ? (
              // eslint-disable-next-line @next/next/no-img-element -- uploaded asset preview
              <img src={value} alt="" className="h-full w-full object-contain p-2" />
            ) : (
              <ImagePlus className="h-7 w-7 text-[var(--text-faint)]" />
            )}
            {uploading && (
              <span className="absolute inset-0 flex items-center justify-center bg-[var(--bg)]/80">
                <Loader2 className="h-5 w-5 animate-spin text-[var(--accent)]" />
              </span>
            )}
          </div>

          <div className="text-center">
            <p className="text-sm font-medium text-[var(--text)]">
              {uploading ? t("uploading") : t("dropOrChoose")}
            </p>
            <p className="mt-0.5 text-xs text-[var(--text-faint)]">{t("imageFormats")}</p>
          </div>
        </button>

        <div className="mt-3 flex flex-wrap items-center justify-center gap-2">
          <Button
            type="button"
            variant="secondary"
            size="sm"
            disabled={disabled || uploading}
            onClick={() => inputRef.current?.click()}
          >
            <Upload className="h-3.5 w-3.5" />
            {t("chooseImage")}
          </Button>
          <Button
            type="button"
            variant="ghost"
            size="sm"
            disabled={disabled || uploading}
            onClick={() => setShowUrl((v) => !v)}
          >
            <Link2 className="h-3.5 w-3.5" />
            {showUrl ? t("hideUrl") : t("useUrl")}
          </Button>
        </div>
      </div>

      {showUrl && (
        <input
          type="url"
          value={value}
          onChange={(e) => onChange(e.target.value)}
          disabled={disabled || uploading}
          placeholder={t("urlPlaceholder")}
          className="w-full rounded-lg border border-[var(--border)] bg-[var(--bg)] px-3.5 py-2.5 text-sm text-[var(--text)] placeholder:text-[var(--text-faint)] focus:border-[var(--accent)]/60 focus:outline-none focus:ring-2 focus:ring-[var(--accent)]/40 disabled:cursor-not-allowed disabled:opacity-60"
        />
      )}

      <input
        ref={inputRef}
        type="file"
        accept="image/png,image/jpeg,image/webp,image/svg+xml,image/gif,image/x-icon,.ico"
        className="hidden"
        disabled={disabled || uploading}
        onChange={(e) => handleFile(e.target.files?.[0])}
      />
    </div>
  );
}
