/* Posy site — shared primitives (ported + adapted from the app) */

const { useState, useEffect, useRef } = React;

// ————— Brand Mark —————
const BrandMark = ({ size = 28 }) => (
  <svg viewBox="0 0 40 40" width={size} height={size} xmlns="http://www.w3.org/2000/svg" style={{ display: "block" }}>
    <defs>
      <filter id="inky-bm" x="-20%" y="-20%" width="140%" height="140%">
        <feTurbulence type="fractalNoise" baseFrequency="1.6" numOctaves="2" seed="4"/>
        <feDisplacementMap in="SourceGraphic" scale="1.2" />
      </filter>
    </defs>
    <path
      d="M20 6 C10 6 4 14 4 22 C4 30 12 34 20 34 C26 34 32 30 32 24"
      fill="none" stroke="var(--ink)" strokeWidth="2.5" strokeLinecap="round"
      filter="url(#inky-bm)"
    />
    <path d="M24 12 Q28 16 28 22 Q24 20 22 16 Q23 14 24 12 Z" fill="var(--moss)" opacity="0.85" />
    <circle cx="33" cy="13" r="3" fill="var(--accent)" opacity="0.9" />
  </svg>
);

// ————— Bed sigils —————
const BedSigil = ({ variant = 0, size = 36 }) => {
  const shapes = [
    <g key="0">
      <circle cx="18" cy="20" r="14" fill="var(--sansui-3)" opacity="0.8"/>
      <path d="M18 8 L10 24 H26 Z" fill="var(--moss)" opacity="0.9"/>
      <path d="M18 14 L12 26 H24 Z" fill="var(--moss-deep)" opacity="0.7"/>
    </g>,
    <g key="1">
      <circle cx="18" cy="20" r="14" fill="var(--sansui-2)" opacity="0.7"/>
      <rect x="14" y="8" width="2" height="22" fill="var(--moss-deep)" opacity="0.85"/>
      <rect x="20" y="6" width="2" height="24" fill="var(--moss-deep)" opacity="0.7"/>
      <path d="M16 12 Q22 10 24 14" fill="none" stroke="var(--moss)" strokeWidth="1.2"/>
      <path d="M14 20 Q8 18 6 22" fill="none" stroke="var(--moss)" strokeWidth="1.2"/>
    </g>,
    <g key="2">
      <circle cx="18" cy="20" r="14" fill="var(--sansui-3)" opacity="0.8"/>
      <ellipse cx="18" cy="24" rx="10" ry="4" fill="var(--stone)" opacity="0.85"/>
      <path d="M10 24 Q18 14 26 24" fill="var(--ink-soft)" opacity="0.7"/>
    </g>,
    <g key="3">
      <circle cx="18" cy="20" r="14" fill="var(--sansui-2)" opacity="0.7"/>
      <ellipse cx="18" cy="26" rx="14" ry="6" fill="var(--moss)" opacity="0.7"/>
      <ellipse cx="14" cy="22" rx="4" ry="3" fill="var(--moss-deep)" opacity="0.6"/>
      <ellipse cx="22" cy="24" rx="5" ry="3" fill="var(--moss-deep)" opacity="0.6"/>
    </g>,
    <g key="4">
      <circle cx="18" cy="20" r="14" fill="var(--sansui-3)" opacity="0.8"/>
      <path d="M8 28 Q18 18 28 22" fill="none" stroke="var(--ink-soft)" strokeWidth="1.5"/>
      <path d="M14 22 L16 18 L18 22 L20 18 L22 22" fill="var(--accent)" opacity="0.8"/>
    </g>,
    <g key="5">
      <circle cx="18" cy="20" r="14" fill="var(--sansui-2)" opacity="0.7"/>
      <path d="M18 14 Q14 20 18 26 Q22 20 18 14" fill="var(--moss-soft)" opacity="0.9"/>
      <path d="M12 20 Q18 22 24 20 Q18 24 12 20" fill="var(--moss-deep)" opacity="0.7"/>
    </g>,
  ];
  return (
    <svg viewBox="0 0 36 36" width={size} height={size} xmlns="http://www.w3.org/2000/svg">
      {shapes[variant % shapes.length]}
    </svg>
  );
};

// ————— Hanko seal —————
const Hanko = ({ size = 44 }) => (
  <svg viewBox="0 0 48 48" width={size} height={size} xmlns="http://www.w3.org/2000/svg" className="sway">
    <defs>
      <filter id="rough-hk" x="-10%" y="-10%" width="120%" height="120%">
        <feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="2" seed="7"/>
        <feDisplacementMap in="SourceGraphic" scale="1.5"/>
      </filter>
    </defs>
    <rect x="4" y="4" width="40" height="40" rx="2" fill="var(--accent)" opacity="0.88" filter="url(#rough-hk)"/>
    <g fill="var(--paper)" fontFamily="var(--font-display)" fontSize="13" fontWeight="500" textAnchor="middle">
      <text x="24" y="20">po</text>
      <text x="24" y="36">sy</text>
    </g>
    <line x1="8" y1="26" x2="40" y2="26" stroke="var(--paper)" strokeWidth="0.6" opacity="0.7"/>
  </svg>
);

// ————— Ensō (large atmospheric ring) —————
const Enso = ({ size = 540, opacity = 0.28 }) => (
  <svg viewBox="0 0 200 200" width={size} height={size} xmlns="http://www.w3.org/2000/svg" aria-hidden="true" style={{ opacity }}>
    <defs>
      <filter id="inky-enso" x="-20%" y="-20%" width="140%" height="140%">
        <feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="2" seed="3"/>
        <feDisplacementMap in="SourceGraphic" scale="3.5" />
      </filter>
    </defs>
    <path
      d="M100 20 C45 20 20 55 20 100 C20 150 60 180 100 180 C150 180 180 150 180 108"
      fill="none" stroke="var(--ink)" strokeWidth="4.5" strokeLinecap="round"
      filter="url(#inky-enso)"
    />
  </svg>
);

// ————— Watercolor blob —————
const WatercolorBlob = ({ top, left, right, size = 220, color = "var(--moss-soft)", delay = 0, dur = 18, opacity = 1 }) => (
  <div
    className="watercolor"
    style={{
      top, left, right, width: size, height: size, opacity,
      background: `radial-gradient(circle at 30% 30%, ${color}, transparent 62%)`,
      animation: `float ${dur}s ease-in-out ${delay}s infinite alternate`
    }}
  />
);

// ————— Ambient particles —————
function Particles({ season, intensity = 0.7 }) {
  const canvasRef = useRef(null);
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    let w, h, particles, raf;

    const resize = () => {
      w = canvas.width = window.innerWidth * devicePixelRatio;
      h = canvas.height = window.innerHeight * devicePixelRatio;
      canvas.style.width = window.innerWidth + "px";
      canvas.style.height = window.innerHeight + "px";
    };
    resize();
    window.addEventListener("resize", resize);

    const config = {
      spring: { color: [181, 80, 106], count: 24, size: [2, 6], shape: "petal", speed: 0.3 },
      summer: { color: [90, 107, 63], count: 30, size: [1, 3], shape: "dot", speed: 0.2 },
      autumn: { color: [165, 51, 33], count: 22, size: [3, 7], shape: "leaf", speed: 0.5 },
      winter: { color: [200, 210, 215], count: 40, size: [1, 3], shape: "dot", speed: 0.25 }
    }[season] || { color: [90, 107, 63], count: 30, size: [1, 3], shape: "dot", speed: 0.2 };

    const cnt = Math.round(config.count * intensity);

    particles = Array.from({ length: cnt }, () => ({
      x: Math.random() * w,
      y: Math.random() * h,
      vx: (Math.random() - 0.5) * config.speed * devicePixelRatio,
      vy: (Math.random() * 0.6 + 0.2) * config.speed * devicePixelRatio,
      r: (config.size[0] + Math.random() * (config.size[1] - config.size[0])) * devicePixelRatio,
      a: Math.random() * Math.PI * 2,
      va: (Math.random() - 0.5) * 0.02,
      o: 0.3 + Math.random() * 0.5
    }));

    const [cr, cg, cb] = config.color;

    const tick = () => {
      ctx.clearRect(0, 0, w, h);
      particles.forEach(p => {
        p.x += p.vx + Math.sin(p.a) * 0.3;
        p.y += p.vy;
        p.a += p.va;
        if (p.y > h + 20) { p.y = -20; p.x = Math.random() * w; }
        if (p.x > w + 20) p.x = -20;
        if (p.x < -20) p.x = w + 20;
        ctx.globalAlpha = p.o;
        ctx.fillStyle = `rgb(${cr},${cg},${cb})`;
        if (config.shape === "petal") {
          ctx.save(); ctx.translate(p.x, p.y); ctx.rotate(p.a);
          ctx.beginPath(); ctx.ellipse(0, 0, p.r, p.r * 0.5, 0, 0, Math.PI * 2); ctx.fill();
          ctx.restore();
        } else if (config.shape === "leaf") {
          ctx.save(); ctx.translate(p.x, p.y); ctx.rotate(p.a);
          ctx.beginPath();
          ctx.moveTo(0, -p.r);
          ctx.quadraticCurveTo(p.r * 0.6, 0, 0, p.r);
          ctx.quadraticCurveTo(-p.r * 0.6, 0, 0, -p.r);
          ctx.fill(); ctx.restore();
        } else {
          ctx.beginPath(); ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2); ctx.fill();
        }
      });
      raf = requestAnimationFrame(tick);
    };
    tick();
    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener("resize", resize);
    };
  }, [season, intensity]);

  return <canvas id="particles" ref={canvasRef} />;
}

Object.assign(window, { BrandMark, BedSigil, Hanko, Enso, WatercolorBlob, Particles });
