// Butterfly3D — a CSS preserve-3d butterfly with flapping wings.
// Each butterfly has 4 wings (FL, FR, HL, HR) made of SVG patterns.
// The wings hinge on the body axis; flap = rotateY oscillation.
//
// Props:
//   species  – species object from window.SPECIES
//   size     – pixel scale (wingspan in px on screen)
//   flap     – ms per flap cycle (smaller = faster)
//   tilt     – overall body tilt (degrees, x-axis)
//   pose     – "fly" (flapping) | "rest" (open, still) | "specimen" (open flat)
//   onClick  – click handler

const WingSVG = ({ species, side }) => {
  // side: "fore-left" | "fore-right" | "hind-left" | "hind-right"
  const p = species.palette;
  const isLeft = side.includes("left");
  const isFore = side.includes("fore");
  const id = `${species.id}-${side}`;

  // Base wing shape paths — generic forewing & hindwing silhouettes,
  // mirrored via transform for left/right. ViewBox 100x100.
  const forePath = "M 50,95 C 20,90 5,70 8,40 C 10,18 25,5 50,8 C 70,10 88,25 92,55 C 94,78 80,92 50,95 Z";
  const hindPath = "M 50,90 C 22,92 6,78 10,55 C 14,32 32,18 55,22 C 78,26 92,42 90,65 C 88,82 75,92 50,90 Z";

  const path = isFore ? forePath : hindPath;
  const flip = isLeft ? "scale(-1,1) translate(-100,0)" : "";

  // Pattern rendering varies by species.pattern
  const renderPattern = () => {
    const pat = species.pattern;
    const els = [];

    // Common: subtle radial highlight for "iridescent" feel
    els.push(
      <radialGradient key="hl" id={`hl-${id}`} cx="35%" cy="30%" r="70%">
        <stop offset="0%" stopColor="#ffffff" stopOpacity="0.35" />
        <stop offset="50%" stopColor="#ffffff" stopOpacity="0.08" />
        <stop offset="100%" stopColor="#000000" stopOpacity="0.18" />
      </radialGradient>
    );
    els.push(
      <linearGradient key="bg" id={`bg-${id}`} x1="0%" y1="0%" x2="100%" y2="100%">
        <stop offset="0%" stopColor={isFore ? p.fore : p.hind} />
        <stop offset="100%" stopColor={shade(isFore ? p.fore : p.hind, -10)} />
      </linearGradient>
    );

    return els;
  };

  // Pattern overlay paths per species.pattern style
  const renderOverlay = () => {
    const pat = species.pattern;
    switch (pat) {
      case "swallowtail":
        return (
          <g>
            {/* heavy black veins */}
            <path d="M50,8 L50,90 M30,15 L40,80 M70,15 L60,80 M15,40 L85,40 M12,60 L88,60" stroke={p.veins} strokeWidth="3" fill="none" strokeLinecap="round" opacity="0.95" />
            <path d="M8,40 C20,35 35,38 50,38 C65,38 80,35 92,40" stroke={p.veins} strokeWidth="2" fill="none" />
            {!isFore && <>
              <circle cx="30" cy="70" r="6" fill={p.accent} stroke={p.veins} strokeWidth="1.5" />
              <circle cx="70" cy="70" r="6" fill={p.accent} stroke={p.veins} strokeWidth="1.5" />
              <circle cx="50" cy="80" r="5" fill={p.spots} stroke={p.veins} strokeWidth="1.5" />
            </>}
            <path d={`M ${isFore ? "8" : "10"},${isFore ? "55" : "70"} L ${isFore ? "20" : "25"},${isFore ? "85" : "88"} L ${isFore ? "12" : "16"},${isFore ? "75" : "82"} Z`} fill={p.veins} opacity="0.7" />
          </g>
        );
      case "festoon":
        return (
          <g>
            <path d="M10,30 C30,25 50,28 70,30 C82,32 90,38 90,45" stroke={p.spots} strokeWidth="2.5" fill="none" />
            <path d="M8,55 C25,52 45,55 65,52 C80,50 88,55 90,62" stroke={p.spots} strokeWidth="2" fill="none" />
            <path d="M50,8 L50,88 M30,15 L36,82 M68,15 L62,82" stroke={p.veins} strokeWidth="1.5" fill="none" opacity="0.7" />
            {[20, 35, 50, 65, 80].map((x, i) => (
              <circle key={i} cx={x} cy={isFore ? 75 : 78} r="2.5" fill={p.spots} />
            ))}
            <path d="M5,85 C 15,82 25,88 35,85 C 45,82 55,88 65,85 C 75,82 85,88 95,85" stroke={p.veins} strokeWidth="1.5" fill="none" />
          </g>
        );
      case "blue":
        return (
          <g>
            <path d={path} fill={`url(#bgshine-${id})`} opacity="0.6" />
            <defs>
              <linearGradient id={`bgshine-${id}`} x1="20%" y1="20%" x2="80%" y2="80%">
                <stop offset="0%" stopColor={lighten(p.fore, 25)} />
                <stop offset="100%" stopColor={shade(p.fore, -15)} />
              </linearGradient>
            </defs>
            <path d="M50,15 L50,85 M30,20 L40,80 M70,20 L60,80" stroke={p.veins} strokeWidth="0.8" fill="none" opacity="0.5" />
            {[20, 30, 40, 50, 60, 70, 80].map((x, i) => (
              <circle key={i} cx={x} cy={85} r="1.5" fill={p.spots} />
            ))}
            <path d={path} fill="none" stroke={p.veins} strokeWidth="2" opacity="0.85" />
            {!isFore && p.accent && <circle cx="80" cy="75" r="3" fill={p.accent} stroke={p.veins} strokeWidth="0.8" />}
          </g>
        );
      case "vanessa":
        return (
          <g>
            <path d="M10,25 C25,18 45,20 60,25 L 65,40 L 50,42 L 40,38 Z" fill={p.veins} opacity="0.85" />
            <path d="M50,8 L50,88" stroke={p.veins} strokeWidth="2" />
            <circle cx="25" cy="35" r="4" fill={p.spots} />
            <circle cx="35" cy="28" r="3" fill={p.spots} />
            <circle cx="65" cy="32" r="3.5" fill={p.spots} />
            <circle cx="78" cy="40" r="3" fill={p.spots} />
            <path d="M5,75 C 25,70 50,75 75,70 C 85,68 92,72 92,78" stroke={p.veins} strokeWidth="2.5" fill="none" />
            {!isFore && <>
              <circle cx="30" cy="70" r="2.5" fill={p.veins} />
              <circle cx="50" cy="72" r="2.5" fill={p.veins} />
              <circle cx="70" cy="70" r="2.5" fill={p.veins} />
            </>}
          </g>
        );
      case "cleopatra":
        return (
          <g>
            {isFore && <ellipse cx="55" cy="50" rx="22" ry="28" fill={p.spots} opacity="0.85" />}
            <path d="M50,12 L50,85 M28,18 L38,80 M72,18 L62,80 M15,35 L85,38 M12,58 L88,58" stroke={p.veins} strokeWidth="0.7" fill="none" opacity="0.55" />
            <circle cx="50" cy="48" r="3" fill={p.veins} opacity="0.7" />
          </g>
        );
      case "pasha":
        return (
          <g>
            <path d="M5,55 C 20,52 40,55 60,53 C 78,51 90,55 92,60 L 92,72 C 75,75 50,73 25,75 L 8,72 Z" fill={p.spots} />
            <path d="M50,10 L50,88 M30,18 L38,82 M70,18 L62,82" stroke={p.veins} strokeWidth="1.2" fill="none" opacity="0.7" />
            {!isFore && <>
              <path d="M 20,82 L 28,98 L 24,85 Z" fill={p.veins} />
              <path d="M 60,82 L 68,98 L 64,85 Z" fill={p.veins} />
              <circle cx="35" cy="70" r="2.5" fill={p.veins} />
              <circle cx="65" cy="70" r="2.5" fill={p.veins} />
            </>}
            {isFore && <path d="M10,30 L92,32" stroke={p.accent} strokeWidth="1.5" opacity="0.6" />}
          </g>
        );
      case "clouded":
        return (
          <g>
            <path d="M8,40 C 18,20 35,12 55,12 C 75,14 88,28 92,48 L 92,55 C 75,52 50,55 25,52 L 10,55 Z" fill={p.veins} opacity="0.85" />
            <path d="M50,15 L50,85 M30,18 L38,82 M70,18 L62,82" stroke={p.veins} strokeWidth="0.6" fill="none" opacity="0.5" />
            {isFore && <circle cx="55" cy="42" r="3" fill={p.accent} />}
          </g>
        );
      case "eyespot":
        return (
          <g>
            <path d="M50,12 L50,88 M28,20 L40,82 M72,20 L60,82" stroke={p.veins} strokeWidth="0.8" fill="none" opacity="0.6" />
            {isFore && <>
              <circle cx="65" cy="35" r="8" fill={p.accent} />
              <circle cx="65" cy="35" r="5" fill={p.spots} />
              <circle cx="63" cy="33" r="1.5" fill="#fafafa" />
            </>}
            {!isFore && <>
              <circle cx="50" cy="55" r="5" fill={p.accent} opacity="0.7" />
            </>}
            <path d="M5,75 C 25,72 50,76 75,72 C 85,70 92,74 92,80" stroke={p.veins} strokeWidth="1.5" fill="none" opacity="0.7" />
          </g>
        );
      case "lattice":
        return (
          <g>
            {/* lattice cross-hatching */}
            <g stroke={p.veins} strokeWidth="1" fill="none" opacity="0.75">
              <path d="M50,10 L50,90 M30,15 L40,85 M70,15 L60,85 M15,30 L85,30 M12,50 L88,50 M14,70 L86,70" />
            </g>
            <g stroke={p.veins} strokeWidth="0.6" fill="none" opacity="0.5">
              <path d="M20,20 L80,20 M22,40 L78,40 M20,60 L80,60 M25,80 L75,80" />
            </g>
            {isFore && <>
              <circle cx="68" cy="35" r="3" fill={p.spots} />
              <circle cx="68" cy="35" r="1" fill="#fafafa" />
            </>}
            {!isFore && <>
              <circle cx="40" cy="60" r="2.5" fill={p.spots} />
              <circle cx="60" cy="60" r="2.5" fill={p.spots} />
            </>}
          </g>
        );
      case "white":
        return (
          <g>
            <path d="M50,12 L50,85 M30,20 L38,80 M70,20 L62,80" stroke={p.veins} strokeWidth="0.5" fill="none" opacity="0.6" />
            {isFore && <>
              <circle cx="60" cy="38" r="4.5" fill={p.spots} opacity="0.85" />
              <path d="M 8,18 L 22,28 L 14,20 Z" fill={p.spots} opacity="0.8" />
            </>}
            <path d="M5,80 C 25,76 50,80 75,76 C 85,74 92,78 92,82" stroke={p.accent} strokeWidth="0.8" fill="none" opacity="0.6" />
          </g>
        );
      case "skipper":
        return (
          <g>
            <ellipse cx="50" cy="50" rx="35" ry="30" fill={p.accent} opacity="0.4" />
            <g stroke={p.veins} strokeWidth="0.8" fill="none" opacity="0.7">
              <path d="M50,15 L50,85 M30,20 L38,80 M70,20 L62,80 M15,40 L85,42 M12,60 L88,60" />
            </g>
            {[25, 40, 55, 70].map((x, i) => (
              <rect key={i} x={x - 2} y={isFore ? 30 : 50} width="4" height="6" fill={p.spots} opacity="0.85" />
            ))}
          </g>
        );
      case "grayling":
        return (
          <g>
            <path d="M10,40 C 25,35 45,38 65,36 C 80,34 90,40 92,48 L 92,55 C 75,52 50,55 25,52 L 10,55 Z" fill={p.accent} opacity="0.7" />
            <path d="M50,12 L50,88 M30,20 L38,82 M70,20 L62,82" stroke={p.veins} strokeWidth="0.7" fill="none" opacity="0.6" />
            {isFore && <>
              <circle cx="68" cy="42" r="5" fill={p.veins} />
              <circle cx="67" cy="41" r="1.5" fill={p.spots} />
              <circle cx="32" cy="42" r="3" fill={p.veins} />
            </>}
          </g>
        );
      default:
        return (
          <g>
            <path d="M50,15 L50,85 M30,20 L38,80 M70,20 L62,80" stroke={p.veins} strokeWidth="1" fill="none" opacity="0.7" />
          </g>
        );
    }
  };

  return (
    <div style={{ width: "100%", height: "100%", transform: isLeft ? "scaleX(-1)" : "none", transformOrigin: "center" }}>
      <svg viewBox="0 0 100 100" preserveAspectRatio="none" style={{ width: "100%", height: "100%", overflow: "visible" }}>
        <defs>{renderPattern()}</defs>
        {/* base wing shape, color */}
        <path d={path} fill={`url(#bg-${id})`} stroke={p.veins} strokeWidth="1.2" />
        {/* pattern */}
        <g style={{ clipPath: `path('${path}')` }}>
          {renderOverlay()}
        </g>
        {/* highlight */}
        <path d={path} fill={`url(#hl-${id})`} pointerEvents="none" />
        {/* outer rim */}
        <path d={path} fill="none" stroke={p.veins} strokeWidth="1.5" opacity="0.85" />
      </svg>
    </div>
  );
};

// utility color helpers
function shade(hex, pct) {
  const f = parseInt(hex.slice(1), 16);
  const t = pct < 0 ? 0 : 255;
  const p = Math.abs(pct) / 100;
  const R = f >> 16, G = (f >> 8) & 0xff, B = f & 0xff;
  const r = Math.round((t - R) * p) + R;
  const g = Math.round((t - G) * p) + G;
  const b = Math.round((t - B) * p) + B;
  return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
function lighten(hex, pct) { return shade(hex, pct); }

const Butterfly3D = ({ species, size = 120, flap = 280, tilt = 0, pose = "fly", onClick, style = {}, paused = false }) => {
  // wings at rest open ~110° between, flapping toward 30° during flap.
  // use CSS animation; pose === "rest" → open at 160°, no animation.
  const wingW = size;
  const wingH = size * 0.95;

  const animClass = pose === "fly" ? "bf-flap" : pose === "specimen" ? "bf-flat" : "bf-rest";

  return (
    <div
      className="butterfly3d"
      onClick={onClick}
      style={{
        width: size * 2,
        height: size,
        position: "relative",
        transformStyle: "preserve-3d",
        cursor: onClick ? "pointer" : "default",
        ...style,
      }}
    >
      <div
        style={{
          position: "absolute",
          inset: 0,
          transformStyle: "preserve-3d",
          transform: `rotateX(${tilt}deg)`,
          animationPlayState: paused ? "paused" : "running",
        }}
      >
        {/* body */}
        <div
          style={{
            position: "absolute",
            left: "50%",
            top: "50%",
            width: size * 0.08,
            height: size * 0.55,
            background: `linear-gradient(180deg, #1a1a1a 0%, #2a2a1a 50%, #1a1a1a 100%)`,
            borderRadius: "50%",
            transform: `translate(-50%, -50%)`,
            boxShadow: "0 0 4px rgba(0,0,0,0.4)",
            zIndex: 5,
          }}
        />
        {/* head */}
        <div
          style={{
            position: "absolute",
            left: "50%",
            top: `calc(50% - ${size * 0.28}px)`,
            width: size * 0.1,
            height: size * 0.1,
            background: "#1a1a1a",
            borderRadius: "50%",
            transform: "translate(-50%, -50%)",
            zIndex: 6,
          }}
        />
        {/* antennae */}
        <svg
          style={{ position: "absolute", left: "50%", top: `calc(50% - ${size * 0.45}px)`, width: size * 0.4, height: size * 0.25, transform: "translateX(-50%)", overflow: "visible", zIndex: 6 }}
          viewBox="0 0 40 25"
        >
          <path d="M 20,25 Q 12,15 8,2" stroke="#1a1a1a" strokeWidth="0.8" fill="none" strokeLinecap="round" />
          <path d="M 20,25 Q 28,15 32,2" stroke="#1a1a1a" strokeWidth="0.8" fill="none" strokeLinecap="round" />
          <circle cx="8" cy="2" r="1" fill="#1a1a1a" />
          <circle cx="32" cy="2" r="1" fill="#1a1a1a" />
        </svg>

        {/* LEFT WINGS */}
        <div
          className={`bf-wing-left ${animClass}`}
          style={{
            position: "absolute",
            right: "50%",
            top: "50%",
            width: wingW,
            height: wingH,
            transformOrigin: "100% 50%",
            transform: "translateY(-50%)",
            animationDuration: `${flap}ms`,
          }}
        >
          {/* hindwing (behind) */}
          <div style={{ position: "absolute", right: 0, top: "20%", width: "85%", height: "85%", transform: "translateZ(-1px)" }}>
            <WingSVG species={species} side="hind-left" />
          </div>
          {/* forewing */}
          <div style={{ position: "absolute", right: "5%", top: "-5%", width: "95%", height: "85%" }}>
            <WingSVG species={species} side="fore-left" />
          </div>
        </div>

        {/* RIGHT WINGS */}
        <div
          className={`bf-wing-right ${animClass}`}
          style={{
            position: "absolute",
            left: "50%",
            top: "50%",
            width: wingW,
            height: wingH,
            transformOrigin: "0% 50%",
            transform: "translateY(-50%)",
            animationDuration: `${flap}ms`,
          }}
        >
          <div style={{ position: "absolute", left: 0, top: "20%", width: "85%", height: "85%", transform: "translateZ(-1px)" }}>
            <WingSVG species={species} side="hind-right" />
          </div>
          <div style={{ position: "absolute", left: "5%", top: "-5%", width: "95%", height: "85%" }}>
            <WingSVG species={species} side="fore-right" />
          </div>
        </div>
      </div>
    </div>
  );
};

window.Butterfly3D = Butterfly3D;
