// pearl.jsx — Canvas pearl renderer + drop animation + 360° rotation
// Provides: <PearlCanvas>, <PearlHeroCanvas>, <Pearl360>

// ── Single pearl drawing helper ─────────────────────────────────────────────
// Draws a photorealistic pearl on a canvas ctx at given cx,cy,r.
// hue shift in [-1..1] warps the colour; darkness in [0..1] makes it black.
function drawPearl(ctx, cx, cy, r, opts = {}) {
  const {
    darkness = 0,         // 0 white — 1 black
    hueShift = 0,         // -1 pink/warm … 1 green/cool
    highlightAngle = -0.7, // radians, approx top-left
    secondarySparkle = 0.6,
    opacity = 1,
    overtone = null,      // force a specific [r,g,b]
  } = opts;

  ctx.save();
  ctx.globalAlpha = opacity;

  // Base body: radial gradient from highlight to dark edge
  const hx = cx + Math.cos(highlightAngle) * r * 0.35;
  const hy = cy + Math.sin(highlightAngle) * r * 0.35;

  const base = hexMix(248, 245, 240, 12, 12, 12, darkness);
  const mid  = hexMix(232, 222, 208, 26, 26, 24, darkness);
  const edge = hexMix(168, 161, 154, 4, 4, 4, darkness);

  // Apply a subtle overtone for iridescence
  let tintR = 0, tintG = 0, tintB = 0;
  if (overtone) { [tintR, tintG, tintB] = overtone; }
  else if (hueShift < 0) { tintR = -hueShift * 14; tintG = hueShift * 6; tintB = -hueShift * 2; } // pink
  else                   { tintR = -hueShift * 4; tintG = hueShift * 10; tintB = hueShift * 6; }  // green

  const body = ctx.createRadialGradient(hx, hy, r * 0.05, cx, cy, r);
  body.addColorStop(0,   rgbStr(base.r + 6,  base.g + 6,  base.b + 6));
  body.addColorStop(0.35, rgbStr(mid.r + tintR, mid.g + tintG, mid.b + tintB));
  body.addColorStop(0.75, rgbStr(mid.r * 0.8, mid.g * 0.8, mid.b * 0.82));
  body.addColorStop(1,   rgbStr(edge.r, edge.g, edge.b));

  ctx.fillStyle = body;
  ctx.beginPath();
  ctx.arc(cx, cy, r, 0, Math.PI * 2);
  ctx.fill();

  // Inner shadow at the "non-lit" side
  const sx = cx - Math.cos(highlightAngle) * r * 0.4;
  const sy = cy - Math.sin(highlightAngle) * r * 0.4;
  const shadow = ctx.createRadialGradient(sx, sy, r * 0.1, sx, sy, r * 1.2);
  shadow.addColorStop(0, "rgba(0,0,0,0.0)");
  shadow.addColorStop(0.6, `rgba(0,0,0,${0.1 + darkness * 0.15})`);
  shadow.addColorStop(1, `rgba(0,0,0,${0.22 + darkness * 0.2})`);
  ctx.fillStyle = shadow;
  ctx.beginPath();
  ctx.arc(cx, cy, r, 0, Math.PI * 2);
  ctx.fill();

  // Primary highlight (crescent)
  const hlR = r * 0.38;
  const highlight = ctx.createRadialGradient(hx, hy, 0, hx, hy, hlR);
  highlight.addColorStop(0, `rgba(255,255,255,${0.9 - darkness * 0.3})`);
  highlight.addColorStop(0.5, `rgba(255,255,255,${0.3 - darkness * 0.15})`);
  highlight.addColorStop(1, "rgba(255,255,255,0)");
  ctx.fillStyle = highlight;
  ctx.beginPath();
  ctx.arc(cx, cy, r, 0, Math.PI * 2);
  ctx.fill();

  // Secondary sparkle — small bright pinpoint inside the highlight
  if (secondarySparkle > 0) {
    const ssR = r * 0.08;
    const ssx = hx - r * 0.04;
    const ssy = hy - r * 0.04;
    const ss = ctx.createRadialGradient(ssx, ssy, 0, ssx, ssy, ssR);
    ss.addColorStop(0, `rgba(255,255,255,${secondarySparkle})`);
    ss.addColorStop(1, "rgba(255,255,255,0)");
    ctx.fillStyle = ss;
    ctx.beginPath();
    ctx.arc(ssx, ssy, ssR, 0, Math.PI * 2);
    ctx.fill();
  }

  // Bottom reflected glow (from ambient light bouncing up)
  const refR = r * 0.5;
  const refx = cx - Math.cos(highlightAngle) * r * 0.55;
  const refy = cy - Math.sin(highlightAngle) * r * 0.55;
  const ref = ctx.createRadialGradient(refx, refy, 0, refx, refy, refR);
  ref.addColorStop(0, `rgba(255,255,255,${0.12 - darkness * 0.1})`);
  ref.addColorStop(1, "rgba(255,255,255,0)");
  ctx.fillStyle = ref;
  ctx.beginPath();
  ctx.arc(cx, cy, r, 0, Math.PI * 2);
  ctx.fill();

  ctx.restore();
}

function hexMix(r1,g1,b1,r2,g2,b2,t) {
  return { r: r1 + (r2 - r1) * t, g: g1 + (g2 - g1) * t, b: b1 + (b2 - b1) * t };
}
function rgbStr(r,g,b) {
  return `rgb(${Math.round(r)},${Math.round(g)},${Math.round(b)})`;
}

// ── <PearlCanvas> — a single still pearl ────────────────────────────────────
function PearlCanvas({ size = 220, darkness = 0, hueShift = 0, overtone = null, className = "", style = {} }) {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const cv = ref.current;
    if (!cv) return;
    const dpr = Math.min(window.devicePixelRatio || 1, 2);
    cv.width = size * dpr;
    cv.height = size * dpr;
    cv.style.width = size + "px";
    cv.style.height = size + "px";
    const ctx = cv.getContext("2d");
    ctx.scale(dpr, dpr);
    ctx.clearRect(0, 0, size, size);
    drawPearl(ctx, size / 2, size / 2, size * 0.42, { darkness, hueShift, overtone });
  }, [size, darkness, hueShift, overtone]);
  return <canvas ref={ref} className={className} style={style} />;
}

// ── <PearlHeroCanvas> — pearls drift downward through dark space ────────────
// Physics: gentle gravity, air drag, spawn at top, loop. Blurred motion.
function PearlHeroCanvas({
  intensity = 1.0,       // multiplier for pearl count / gradient strength
  theme = "light",       // "light" | "dark"
  style = {},
  interactive = true,
}) {
  const ref = React.useRef(null);
  const rafRef = React.useRef(null);
  const pearlsRef = React.useRef([]);
  const sizeRef = React.useRef({ w: 0, h: 0, dpr: 1 });
  const mouseRef = React.useRef({ x: -9999, y: -9999, active: false });

  React.useEffect(() => {
    const cv = ref.current;
    if (!cv) return;
    const ctx = cv.getContext("2d");

    const resize = () => {
      const rect = cv.getBoundingClientRect();
      const dpr = Math.min(window.devicePixelRatio || 1, 2);
      cv.width = rect.width * dpr;
      cv.height = rect.height * dpr;
      sizeRef.current = { w: rect.width, h: rect.height, dpr };
    };
    resize();
    const ro = new ResizeObserver(resize);
    ro.observe(cv);

    // Spawn pearls
    const PEARL_COUNT = Math.round(28 * intensity);
    const pearls = [];
    for (let i = 0; i < PEARL_COUNT; i++) {
      pearls.push(spawnPearl(true));
    }
    pearlsRef.current = pearls;

    function spawnPearl(initial = false) {
      const { w, h } = sizeRef.current;
      const r = 10 + Math.random() * 40;
      const depth = Math.random(); // 0 = far, 1 = near
      return {
        x: Math.random() * (w || 1000),
        y: initial ? Math.random() * (h || 600) : -r * 2,
        r,
        vy: 0.4 + Math.random() * 0.6 + depth * 0.6,
        vx: (Math.random() - 0.5) * 0.3,
        sway: Math.random() * Math.PI * 2,
        swaySpd: 0.005 + Math.random() * 0.01,
        darkness: Math.random() < 0.35 ? 0.85 + Math.random() * 0.1 : Math.random() * 0.08,
        hueShift: (Math.random() - 0.5) * 1.4,
        depth,
        opacity: 0.55 + depth * 0.45,
      };
    }

    function step() {
      const { w, h, dpr } = sizeRef.current;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      ctx.clearRect(0, 0, w, h);

      // Background fill
      if (theme === "dark") {
        const g = ctx.createRadialGradient(w * 0.5, h * 0.5, 0, w * 0.5, h * 0.5, Math.max(w, h) * 0.7);
        g.addColorStop(0, "#15120F");
        g.addColorStop(1, "#060504");
        ctx.fillStyle = g;
        ctx.fillRect(0, 0, w, h);
      } else {
        const g = ctx.createLinearGradient(0, 0, 0, h);
        g.addColorStop(0, "#F8F5F0");
        g.addColorStop(1, "#ECE5D8");
        ctx.fillStyle = g;
        ctx.fillRect(0, 0, w, h);
      }

      // Sort by depth so near pearls overlap far ones
      pearlsRef.current.sort((a, b) => a.depth - b.depth);

      for (const p of pearlsRef.current) {
        p.sway += p.swaySpd;
        p.y += p.vy * (0.5 + p.depth * 0.8);
        p.x += p.vx + Math.sin(p.sway) * 0.3;

        // Mouse repulsion
        if (interactive && mouseRef.current.active) {
          const dx = p.x - mouseRef.current.x;
          const dy = p.y - mouseRef.current.y;
          const d2 = dx * dx + dy * dy;
          const R = 140;
          if (d2 < R * R && d2 > 1) {
            const d = Math.sqrt(d2);
            const force = (1 - d / R) * 3;
            p.x += (dx / d) * force;
            p.y += (dy / d) * force;
          }
        }

        // Respawn when off bottom
        if (p.y - p.r > h) {
          Object.assign(p, spawnPearl(false), { y: -p.r * 2, x: Math.random() * w });
        }
        if (p.x < -p.r * 2) p.x = w + p.r;
        if (p.x > w + p.r * 2) p.x = -p.r;

        drawPearl(ctx, p.x, p.y, p.r, {
          darkness: p.darkness,
          hueShift: p.hueShift,
          opacity: p.opacity,
        });
      }

      rafRef.current = requestAnimationFrame(step);
    }
    rafRef.current = requestAnimationFrame(step);

    const onMove = (e) => {
      const rect = cv.getBoundingClientRect();
      mouseRef.current.x = e.clientX - rect.left;
      mouseRef.current.y = e.clientY - rect.top;
      mouseRef.current.active = true;
    };
    const onLeave = () => { mouseRef.current.active = false; };
    if (interactive) {
      cv.addEventListener("mousemove", onMove);
      cv.addEventListener("mouseleave", onLeave);
    }

    return () => {
      cancelAnimationFrame(rafRef.current);
      ro.disconnect();
      if (interactive) {
        cv.removeEventListener("mousemove", onMove);
        cv.removeEventListener("mouseleave", onLeave);
      }
    };
  }, [intensity, theme, interactive]);

  return <canvas ref={ref} style={{ width: "100%", height: "100%", display: "block", ...style }} />;
}

// ── <Pearl360> — pearl rotates on drag / auto ───────────────────────────────
// For PDP: simulates 360° product rotation. Draws 36 "frames" of a pearl
// necklace or ring by rotating the lighting angle & pearl positions.
function Pearl360({
  mode = "necklace",     // "necklace" | "ring" | "earring"
  darkness = 0,
  hueShift = 0,
  autoRotate = true,
  size = 640,
}) {
  const ref = React.useRef(null);
  const rafRef = React.useRef(null);
  const angleRef = React.useRef(0);
  const draggingRef = React.useRef(null);
  const autoRef = React.useRef(autoRotate);

  React.useEffect(() => { autoRef.current = autoRotate; }, [autoRotate]);

  React.useEffect(() => {
    const cv = ref.current;
    if (!cv) return;
    const ctx = cv.getContext("2d");
    const dpr = Math.min(window.devicePixelRatio || 1, 2);

    const resize = () => {
      const rect = cv.getBoundingClientRect();
      cv.width = rect.width * dpr;
      cv.height = rect.height * dpr;
    };
    resize();
    const ro = new ResizeObserver(resize);
    ro.observe(cv);

    function draw() {
      const rect = cv.getBoundingClientRect();
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      ctx.clearRect(0, 0, rect.width, rect.height);

      const cx = rect.width / 2;
      const cy = rect.height / 2;
      const angle = angleRef.current;

      if (mode === "necklace") {
        drawNecklace(ctx, cx, cy, Math.min(rect.width, rect.height) * 0.4, angle, darkness, hueShift);
      } else if (mode === "ring") {
        drawRing(ctx, cx, cy, Math.min(rect.width, rect.height) * 0.3, angle, darkness, hueShift);
      } else {
        drawEarring(ctx, cx, cy, Math.min(rect.width, rect.height) * 0.35, angle, darkness, hueShift);
      }

      if (autoRef.current && !draggingRef.current) {
        angleRef.current += 0.006;
      }
      rafRef.current = requestAnimationFrame(draw);
    }
    rafRef.current = requestAnimationFrame(draw);

    const onDown = (e) => {
      draggingRef.current = { x: e.clientX, a: angleRef.current };
    };
    const onMove = (e) => {
      if (!draggingRef.current) return;
      const dx = e.clientX - draggingRef.current.x;
      angleRef.current = draggingRef.current.a + dx * 0.012;
    };
    const onUp = () => { draggingRef.current = null; };

    cv.addEventListener("mousedown", onDown);
    window.addEventListener("mousemove", onMove);
    window.addEventListener("mouseup", onUp);

    return () => {
      cancelAnimationFrame(rafRef.current);
      ro.disconnect();
      cv.removeEventListener("mousedown", onDown);
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseup", onUp);
    };
  }, [mode, darkness, hueShift]);

  return <canvas ref={ref} style={{ width: "100%", height: "100%", display: "block", cursor: "grab" }} />;
}

function drawNecklace(ctx, cx, cy, R, angle, darkness, hueShift) {
  // Draw a U-shaped strand of pearls; rotate around X axis via scaleY
  const N = 31;
  const openingAngle = Math.PI * 1.1; // arc span
  const start = -Math.PI - (Math.PI * 1.1 - Math.PI) / 2; // top-left
  const tilt = Math.cos(angle) * 0.3; // front-back tilt
  const scaleY = 1 - Math.abs(Math.sin(angle)) * 0.15;

  // Chain subtle
  ctx.strokeStyle = `rgba(${darkness > 0.5 ? "60,58,54" : "140,130,118"},0.2)`;
  ctx.lineWidth = 1;

  const pts = [];
  for (let i = 0; i < N; i++) {
    const t = i / (N - 1);
    const a = start + t * openingAngle;
    // size: largest at centre
    const sizeFactor = 0.7 + 0.45 * Math.sin(t * Math.PI);
    const radius = R * 1.05;
    const x = cx + Math.cos(a) * radius;
    const y = cy + Math.sin(a) * radius * scaleY + tilt * 8 * Math.sin(t * Math.PI);
    pts.push({ x, y, r: R * 0.075 * sizeFactor, t });
  }

  // Draw threading line
  ctx.beginPath();
  pts.forEach((p, i) => i === 0 ? ctx.moveTo(p.x, p.y) : ctx.lineTo(p.x, p.y));
  ctx.stroke();

  // Draw pearls in order (back first for depth)
  pts.forEach((p) => {
    drawPearl(ctx, p.x, p.y, p.r, { darkness, hueShift, highlightAngle: -0.7 + angle * 0.3 });
  });

  // Clasp / diamond accent at centre-bottom (or rotated)
  const clasp = pts[Math.floor(N / 2)];
  ctx.save();
  ctx.fillStyle = "#ffffff";
  ctx.shadowColor = "#ffffff";
  ctx.shadowBlur = 8;
  // Little diamond
  ctx.beginPath();
  ctx.moveTo(clasp.x, clasp.y + R * 0.17);
  ctx.lineTo(clasp.x + R * 0.03, clasp.y + R * 0.22);
  ctx.lineTo(clasp.x, clasp.y + R * 0.27);
  ctx.lineTo(clasp.x - R * 0.03, clasp.y + R * 0.22);
  ctx.closePath();
  ctx.fill();
  ctx.restore();
}

function drawRing(ctx, cx, cy, R, angle, darkness, hueShift) {
  // Simple ring: metal band (ellipse) with a large pearl on top
  const scaleY = 0.35 + Math.abs(Math.cos(angle)) * 0.15;
  ctx.save();

  // Band (back half)
  ctx.strokeStyle = darkness > 0.5 ? "#C9C2B5" : "#D8D3CB";
  ctx.lineWidth = R * 0.14;
  ctx.beginPath();
  ctx.ellipse(cx, cy + R * 0.3, R * 0.85, R * 0.85 * scaleY, 0, 0, Math.PI, true);
  ctx.stroke();

  // Pearl on top
  drawPearl(ctx, cx, cy - R * 0.2, R * 0.55, {
    darkness, hueShift, highlightAngle: -0.7 + angle * 0.4,
  });

  // Diamond accents (pavé hint)
  for (let i = 0; i < 6; i++) {
    const a = Math.PI + i * (Math.PI / 5) + angle * 0.3;
    const px = cx + Math.cos(a) * R * 0.58;
    const py = cy - R * 0.2 + Math.sin(a) * R * 0.58;
    ctx.fillStyle = "rgba(255,255,255,0.95)";
    ctx.beginPath();
    ctx.arc(px, py, R * 0.04, 0, Math.PI * 2);
    ctx.fill();
  }

  // Band (front half)
  ctx.strokeStyle = darkness > 0.5 ? "#E4DFD3" : "#EFEBE3";
  ctx.lineWidth = R * 0.14;
  ctx.beginPath();
  ctx.ellipse(cx, cy + R * 0.3, R * 0.85, R * 0.85 * scaleY, 0, 0, Math.PI, false);
  ctx.stroke();

  ctx.restore();
}

function drawEarring(ctx, cx, cy, R, angle, darkness, hueShift) {
  // Top pearl + diamond drop + bottom pearl
  const sway = Math.sin(angle) * 4;
  drawPearl(ctx, cx + sway * 0.5, cy - R * 0.55, R * 0.28, {
    darkness, hueShift, highlightAngle: -0.7 + angle * 0.3,
  });
  // Diamond diamond
  ctx.save();
  ctx.fillStyle = "rgba(255,255,255,0.95)";
  ctx.translate(cx + sway * 0.75, cy - R * 0.1);
  ctx.rotate(Math.PI / 4);
  ctx.fillRect(-R * 0.08, -R * 0.08, R * 0.16, R * 0.16);
  ctx.restore();
  // Bottom big pearl
  drawPearl(ctx, cx + sway, cy + R * 0.4, R * 0.42, {
    darkness, hueShift, highlightAngle: -0.7 + angle * 0.3,
  });
}

Object.assign(window, { drawPearl, PearlCanvas, PearlHeroCanvas, Pearl360 });
