import { useState, useRef, type DragEvent } from "react";
import { Upload, X, Image as ImageIcon } from "lucide-react";
import { toast } from "sonner";

import { adminBlogApi, absolutizeApiUrl } from "@/lib/admin-blog";
import { Button, cn } from "@rubis/ui";

const ACCEPTED = "image/jpeg,image/png,image/webp";

type Props = {
  value: string | null;
  alt: string | null;
  onChange: (next: { url: string | null; alt: string | null }) => void;
};

/**
 * HeroImageUpload — drag & drop image (JPEG/PNG/WebP, max 4 MB).
 * Upload va dans MinIO via /api/v1/admin/uploads, l'URL renvoyée est stockée
 * dans posts.hero_image_url. L'alt est requis pour publier (SEO + a11y).
 */
export function HeroImageUpload({ value, alt, onChange }: Props) {
  const [uploading, setUploading] = useState(false);
  const [dragOver, setDragOver] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);

  const handleFile = async (file: File) => {
    setUploading(true);
    try {
      const result = await adminBlogApi.uploadImage(file);
      onChange({ url: result.url, alt: alt ?? deriveAltFromFilename(file.name) });
      toast.success("Image uploadée.");
    } catch (err) {
      const msg = err instanceof Error ? err.message : "Échec upload";
      toast.error(`Échec upload : ${msg}`);
    } finally {
      setUploading(false);
    }
  };

  const onDrop = (e: DragEvent) => {
    e.preventDefault();
    setDragOver(false);
    const file = e.dataTransfer.files[0];
    if (file) {
      void handleFile(file);
    }
  };

  return (
    <div className="space-y-3">
      {/* Single hidden input — réutilisé par le drop zone et le bouton "Remplacer". */}
      <input
        ref={inputRef}
        type="file"
        accept={ACCEPTED}
        className="sr-only"
        onChange={(e) => {
          const file = e.target.files?.[0];
          if (file) void handleFile(file);
          e.target.value = "";
        }}
      />
      {value ? (
        <div className="relative group">
          <img
            src={absolutizeApiUrl(value)}
            alt={alt ?? ""}
            className="w-full aspect-[16/9] object-cover rounded-card border border-line"
          />
          <button
            type="button"
            onClick={() => onChange({ url: null, alt: null })}
            className="absolute top-3 right-3 size-8 rounded-full bg-white/90 backdrop-blur border border-line flex items-center justify-center text-ink-2 hover:text-rubis-deep hover:bg-white transition-colors shadow-soft"
            title="Retirer l'image"
            aria-label="Retirer l'image"
          >
            <X size={16} />
          </button>
        </div>
      ) : (
        <div
          onDragOver={(e) => {
            e.preventDefault();
            setDragOver(true);
          }}
          onDragLeave={() => setDragOver(false)}
          onDrop={onDrop}
          onClick={() => inputRef.current?.click()}
          className={cn(
            "relative cursor-pointer w-full aspect-[16/9] rounded-card border-2 border-dashed",
            "flex flex-col items-center justify-center gap-3 transition-colors",
            dragOver
              ? "border-rubis bg-rubis-glow/40"
              : "border-line bg-cream-2 hover:border-ink-3 hover:bg-cream-2/60",
          )}
        >
          {uploading ? (
            <div className="flex flex-col items-center gap-2 text-ink-2">
              <div className="size-8 border-2 border-current border-r-transparent rounded-full animate-spin" />
              <span className="text-[13px]">Upload en cours…</span>
            </div>
          ) : (
            <>
              <div className="size-12 rounded-full bg-white border border-line flex items-center justify-center text-ink-3">
                <Upload size={20} />
              </div>
              <div className="text-center">
                <div className="font-display font-semibold text-[15px] text-ink">
                  Drag & drop ou clique pour uploader
                </div>
                <div className="text-[12.5px] text-ink-3 mt-0.5">
                  JPEG, PNG, WebP — max 4 MB · ratio 16:9 idéal
                </div>
              </div>
            </>
          )}
        </div>
      )}

      {/* Alt text — bloquant pour publier */}
      <div>
        <label className="block text-[12px] uppercase tracking-[0.08em] font-semibold text-ink-3 mb-1.5">
          Texte alternatif (alt) — requis pour publier
        </label>
        <input
          type="text"
          value={alt ?? ""}
          onChange={(e) => onChange({ url: value, alt: e.target.value })}
          placeholder="ex. Une facture en papier traversée par un rubis facetté"
          maxLength={250}
          className="w-full px-3 py-2 rounded-default border border-line bg-white text-[14px] text-ink focus:border-rubis focus:outline-none focus:ring-4 focus:ring-rubis-glow/40"
        />
        <div className="text-[11.5px] text-ink-3 mt-1">
          Décris l'image pour les lecteurs d'écran et le SEO. {alt?.length ?? 0}/250.
        </div>
      </div>

      {value && !uploading && (
        <Button
          type="button"
          variant="ghost"
          size="sm"
          onClick={() => inputRef.current?.click()}
        >
          <ImageIcon size={14} />
          Remplacer l'image
        </Button>
      )}
    </div>
  );
}

function deriveAltFromFilename(filename: string): string {
  return filename
    .replace(/\.[^.]+$/, "")
    .replace(/[-_]+/g, " ")
    .replace(/\s+/g, " ")
    .trim();
}
