// Shared botanical components — leaves, frames, ornaments
// All exported to window for cross-script use.

const { useEffect, useRef, useState } = React;

/* ---------- Image compression utility (used by Editor.jsx + Fiche.jsx) ----------
   Compresse une photo uploadée AVANT l'envoi base64 vers Supabase :
   - redimensionne à maxDim px max (préserve le ratio)
   - recompresse en WebP qualité 0.82 (fallback JPEG si WebP non supporté)
   Conséquence : une photo téléphone 4032×3024 / 4-8 Mo passe à ~1500×1125 /
   ~150-300 Ko — facteur ~20× sans perte perceptible. Critique pour le poids
   global des fiches (stockage Supabase JSONB + temps de chargement).
*/
async function compressImage(file, { maxDim = 1500, quality = 0.82 } = {}) {
  if (!file) throw new Error("Aucun fichier fourni");
  const bitmap = await createImageBitmap(file);
  try {
    const scale = Math.min(1, maxDim / Math.max(bitmap.width, bitmap.height));
    const w = Math.max(1, Math.round(bitmap.width * scale));
    const h = Math.max(1, Math.round(bitmap.height * scale));
    const canvas = document.createElement("canvas");
    canvas.width = w;
    canvas.height = h;
    canvas.getContext("2d").drawImage(bitmap, 0, 0, w, h);
    // Tentative WebP, fallback JPEG si non supporté (Safari <14, etc.)
    const webp = canvas.toDataURL("image/webp", quality);
    if (webp.startsWith("data:image/webp")) return webp;
    return canvas.toDataURL("image/jpeg", quality);
  } finally {
    bitmap.close && bitmap.close();
  }
}
window.compressImage = compressImage;

/* ---------- Reveal-on-scroll wrapper ---------- */
function Reveal({ children, delay = 0, as: Tag = "div", className = "", style = {} }) {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const io = new IntersectionObserver(
      (entries) => entries.forEach((e) => {
        if (e.isIntersecting) {
          setTimeout(() => el.classList.add("in"), delay);
          io.unobserve(el);
        }
      }),
      { threshold: 0.12, rootMargin: "0px 0px -40px 0px" }
    );
    io.observe(el);
    return () => io.disconnect();
  }, [delay]);
  return (
    <Tag ref={ref} className={`reveal ${className}`} style={style}>
      {children}
    </Tag>
  );
}

/* ---------- Simple botanical ornament (allowed: lines + circles only) ---------- */
function Ornament({ size = 60, color = "currentColor" }) {
  return (
    <svg width={size} height={size * 0.4} viewBox="0 0 200 80" fill="none" stroke={color} strokeWidth="1">
      <line x1="0" y1="40" x2="200" y2="40" />
      <circle cx="100" cy="40" r="5" fill={color} stroke="none" />
      <circle cx="80" cy="40" r="2" fill={color} stroke="none" />
      <circle cx="120" cy="40" r="2" fill={color} stroke="none" />
      <circle cx="60" cy="40" r="1.2" fill={color} stroke="none" />
      <circle cx="140" cy="40" r="1.2" fill={color} stroke="none" />
    </svg>
  );
}

/* ---------- Botanical placeholder plate ---------- */
// Si `src` est fourni (URL ou DataURL), on affiche la vraie photo par-dessus la
// trame rayée du design — le cadre, les ticks de coin et le label monospace
// restent visibles autour. Sans src, la planche d'herbier vide reste telle quelle.
// `attribution` = URL externe (ex. page Wikipedia) → affiche un petit lien de
// crédit en bas à droite, pour respecter les licences CC-BY-SA.
function Plate({ label = "Photo / planche botanique", aspect = "3/4", style = {}, frame = true, src, attribution, cover = false, children }) {
  return (
    <div
      className={`plate ${frame ? "plate-frame" : ""} ${src ? "plate-has-image" : ""}`}
      data-label={label}
      style={{ aspectRatio: aspect, ...style }}
    >
      {src && (
        <img
          src={src}
          alt={label}
          style={{
            position: "absolute", inset: 0, width: "100%", height: "100%",
            objectFit: cover ? "cover" : "contain",
            objectPosition: "center",
            display: "block"
          }}
        />
      )}
      {children}
    </div>
  );
}

/* ---------- Image-slot wrapper (drop your own image) ---------- */
// Hors environnement Claude Design (serveur Apache classique, file://) le custom
// element `<image-slot>` reste en lecture seule. Pour afficher une vraie photo
// déjà sauvegardée, on bascule sur <Plate src={…}>.
function ImgSlot({ id, label, aspect = "3/4", style = {}, shape = "rect", src }) {
  if (src) {
    return <Plate label={label} aspect={aspect} style={style} src={src} />;
  }
  return (
    <image-slot
      id={id}
      placeholder={label}
      shape={shape}
      style={{ aspectRatio: aspect, display: "block", ...style }}
    ></image-slot>
  );
}

/* ---------- Floating ambient leaves (corner drift) ---------- */
function AmbientLeaves() {
  return (
    <>
      <div className="leaf-drift leaf-1" aria-hidden="true">
        <svg viewBox="0 0 400 400">
          <g fill="none" stroke="#2d4329" strokeWidth="0.8" opacity="0.55">
            <path d="M30,200 Q140,40 360,80" />
            <path d="M30,200 Q140,80 360,80" />
            <path d="M30,200 Q140,120 360,80" />
            <path d="M30,200 Q140,160 360,80" />
            <path d="M30,200 Q140,200 360,80" />
            <path d="M30,200 Q140,240 360,120" />
            <path d="M30,200 Q140,280 360,180" />
            <path d="M30,200 Q140,320 360,260" />
            <path d="M30,200 Q140,360 360,340" />
          </g>
        </svg>
      </div>
      <div className="leaf-drift leaf-2" aria-hidden="true">
        <svg viewBox="0 0 400 400">
          <g fill="none" stroke="#4d6b3e" strokeWidth="0.8" opacity="0.5">
            <path d="M30,200 Q140,40 360,80" />
            <path d="M30,200 Q140,120 360,80" />
            <path d="M30,200 Q140,200 360,80" />
            <path d="M30,200 Q140,280 360,180" />
            <path d="M30,200 Q140,360 360,340" />
          </g>
        </svg>
      </div>
    </>
  );
}

/* ---------- Mini icons (kept extremely simple — lines + circles) ---------- */
const IconLeaf = ({ size = 16 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round">
    <path d="M4 20 Q12 4 20 4 Q20 14 12 20 Q8 22 4 20 Z" />
    <line x1="4" y1="20" x2="14" y2="10" />
  </svg>
);
const IconSearch = ({ size = 16 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round">
    <circle cx="11" cy="11" r="6" />
    <line x1="15.5" y1="15.5" x2="20" y2="20" />
  </svg>
);
const IconArrow = ({ size = 16, rot = 0 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" style={{ transform: `rotate(${rot}deg)` }}>
    <line x1="4" y1="12" x2="20" y2="12" />
    <polyline points="14 6 20 12 14 18" />
  </svg>
);
const IconClose = ({ size = 16 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round">
    <line x1="5" y1="5" x2="19" y2="19" />
    <line x1="19" y1="5" x2="5" y2="19" />
  </svg>
);
const IconBook = ({ size = 16 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round">
    <path d="M4 4 H10 Q12 4 12 6 V20 Q12 18 10 18 H4 Z" />
    <path d="M20 4 H14 Q12 4 12 6 V20 Q12 18 14 18 H20 Z" />
  </svg>
);
const IconPlus = ({ size = 16 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round">
    <line x1="12" y1="5" x2="12" y2="19" />
    <line x1="5" y1="12" x2="19" y2="12" />
  </svg>
);
const IconPrint = ({ size = 16 }) => (
  <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round">
    <polyline points="6 9 6 2 18 2 18 9" />
    <path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2" />
    <rect x="6" y="14" width="12" height="8" />
  </svg>
);

/* ---------- Responsive hook ---------- */
function useMobile(bp = 768) {
  const [m, setM] = React.useState(window.innerWidth < bp);
  React.useEffect(() => {
    const fn = () => setM(window.innerWidth < bp);
    window.addEventListener("resize", fn, { passive: true });
    return () => window.removeEventListener("resize", fn);
  }, [bp]);
  return m;
}

Object.assign(window, {
  Reveal, Ornament, Plate, ImgSlot, AmbientLeaves,
  IconLeaf, IconSearch, IconArrow, IconClose, IconBook, IconPlus, IconPrint,
  useMobile,
});
