// bouquet.jsx — bouquet preview SVG component
// Renders a hand-tied bouquet wrapped in paper/silk/twine, with stems splaying
// out the top and flower heads varying in height for a natural arrangement.
// All flowers are composed of basic shapes (circles + simple paths) per
// project SVG rules.

const FLOWERS = {
  peony:      { label: 'peony',      head: '#c45c6e', center: '#f3d57a', size: 18 },
  daisy:      { label: 'daisy',      head: '#f6efd9', center: '#c8762a', size: 15, ringStroke: '#7a5a3a' },
  lavender:   { label: 'lavender',   head: '#b8a4d0', center: '#7a5a8a', size: 12 },
  marigold:   { label: 'marigold',   head: '#e8a36a', center: '#a8606a', size: 16 },
  cornflower: { label: 'cornflower', head: '#9cbed4', center: '#f3d57a', size: 13 },
  ranunculus: { label: 'ranunculus', head: '#f0c8b8', center: '#c45c6e', size: 14 },
  // foliage / fillers
  babysbreath: { label: "baby's breath", head: '#fbf7ec', center: '#efe7d0', size: 13 },
  eucalyptus:  { label: 'eucalyptus',    head: '#9bb59a', center: '#6b7d5c', size: 14 },
  fern:        { label: 'fern',          head: '#7e9b6e', center: '#4a5d3e', size: 15 },
};

// Deterministic jitter so the bouquet is repeatable.
function jitter(i, seed = 1, range = 1) {
  const x = Math.sin(i * 12.9898 + seed * 78.233) * 43758.5453;
  return ((x - Math.floor(x)) - 0.5) * 2 * range;
}

// Compute a stable position + height for the n-th stem.
function stemPlacement(i, total) {
  // even spread across the wrap mouth (x = -60..60 inside our 320 viewbox)
  const spread = Math.min(80, total * 9 + 24);
  const t = total === 1 ? 0.5 : i / (total - 1);
  const x = (t - 0.5) * spread + jitter(i, 1, 4);
  // angle: outer stems tilt more
  const angle = (t - 0.5) * 22 + jitter(i, 2, 4);
  // height: outer stems shorter
  const heightBase = 230 - Math.abs(t - 0.5) * 50;
  const height = heightBase + jitter(i, 3, 14);
  return { x, angle, height };
}

function Flower({ type, x = 0, y = 0, scale = 1 }) {
  const f = FLOWERS[type] || FLOWERS.peony;
  const r = f.size;
  if (type === 'babysbreath') {
    // airy spray of tiny white blossoms on hair-thin stems
    const pts = [[0,-13],[5,-9],[-5,-9],[8,-3],[-8,-3],[3,-4],[-3,-4],[6,2],[-6,2],[0,3],[2,-1]];
    return (
      <g transform={`translate(${x} ${y}) scale(${scale})`}>
        {pts.map(([px,py],i) => (
          <line key={'s'+i} x1="0" y1="4" x2={px} y2={py} stroke="#9fae7e" strokeWidth="0.6" opacity="0.85" />
        ))}
        {pts.map(([px,py],i) => (
          <circle key={'d'+i} cx={px} cy={py} r="1.85" fill={f.head} stroke="#a7ab83" strokeWidth="0.7" />
        ))}
      </g>
    );
  }
  if (type === 'eucalyptus') {
    // rounded silver-sage leaves in opposite pairs up a short sprig
    const leaves = [];
    [-2,-7,-12].forEach((ly,i) => {
      leaves.push(<ellipse key={'r'+i} cx="4.5" cy={ly} rx="5" ry="3.1" fill={f.head} stroke={f.center} strokeWidth="0.5" transform={`rotate(38 4.5 ${ly})`} />);
      leaves.push(<ellipse key={'l'+i} cx="-4.5" cy={ly} rx="5" ry="3.1" fill={f.head} stroke={f.center} strokeWidth="0.5" transform={`rotate(-38 -4.5 ${ly})`} />);
    });
    return (
      <g transform={`translate(${x} ${y}) scale(${scale})`}>
        <path d="M0 6 Q 1 -8 0 -20" stroke={f.center} strokeWidth="0.8" fill="none" />
        {leaves}
        <ellipse cx="0" cy="-20" rx="3.6" ry="2.7" fill={f.head} stroke={f.center} strokeWidth="0.5" />
      </g>
    );
  }
  if (type === 'fern') {
    // a single green frond — central rib with paired leaflets
    const parts = [<path key="rib" d="M0 6 Q 1 -10 0 -24" stroke={f.center} strokeWidth="1" fill="none" />];
    for (let i = 0; i < 6; i++) {
      const ly = 3 - i * 4.4;
      const len = 7.5 - i * 0.9;
      parts.push(<line key={'r'+i} x1="0" y1={ly} x2={len} y2={ly - 4.5} stroke={f.head} strokeWidth="1.4" strokeLinecap="round" />);
      parts.push(<line key={'l'+i} x1="0" y1={ly} x2={-len} y2={ly - 4.5} stroke={f.head} strokeWidth="1.4" strokeLinecap="round" />);
    }
    return <g transform={`translate(${x} ${y}) scale(${scale})`}>{parts}</g>;
  }
  if (type === 'lavender') {
    // small bud spike
    return (
      <g transform={`translate(${x} ${y}) scale(${scale})`}>
        <ellipse cx="0" cy="0" rx="3" ry="3.6" fill={f.head} />
        <ellipse cx="-3" cy="-5" rx="2.6" ry="3" fill={f.head} />
        <ellipse cx="3" cy="-5" rx="2.6" ry="3" fill={f.head} />
        <ellipse cx="0" cy="-10" rx="2.4" ry="2.8" fill={f.head} />
        <ellipse cx="-2" cy="-14" rx="2" ry="2.5" fill={f.head} />
        <ellipse cx="2" cy="-14" rx="2" ry="2.5" fill={f.head} />
        <ellipse cx="0" cy="-18" rx="1.7" ry="2.2" fill={f.center} />
      </g>
    );
  }
  if (type === 'daisy') {
    // 8 petals around a center
    const petals = [];
    for (let i = 0; i < 8; i++) {
      const a = (i / 8) * Math.PI * 2;
      const px = Math.cos(a) * r * 0.7;
      const py = Math.sin(a) * r * 0.7;
      petals.push(
        <ellipse key={i} cx={px} cy={py} rx={r * 0.55} ry={r * 0.35}
          transform={`rotate(${(a * 180 / Math.PI)} ${px} ${py})`}
          fill={f.head} stroke={f.ringStroke} strokeWidth="0.5" />
      );
    }
    return (
      <g transform={`translate(${x} ${y}) scale(${scale})`}>
        {petals}
        <circle cx="0" cy="0" r={r * 0.42} fill={f.center} />
      </g>
    );
  }
  if (type === 'cornflower') {
    // jagged round
    const petals = [];
    for (let i = 0; i < 6; i++) {
      const a = (i / 6) * Math.PI * 2;
      const px = Math.cos(a) * r * 0.65;
      const py = Math.sin(a) * r * 0.65;
      petals.push(<circle key={i} cx={px} cy={py} r={r * 0.55} fill={f.head} />);
    }
    return (
      <g transform={`translate(${x} ${y}) scale(${scale})`}>
        {petals}
        <circle cx="0" cy="0" r={r * 0.36} fill={f.center} />
      </g>
    );
  }
  // peony / marigold / ranunculus — layered round
  const outer = [];
  for (let i = 0; i < 6; i++) {
    const a = (i / 6) * Math.PI * 2;
    outer.push(<circle key={i} cx={Math.cos(a) * r * 0.55} cy={Math.sin(a) * r * 0.55} r={r * 0.55} fill={f.head} />);
  }
  const inner = [];
  for (let i = 0; i < 5; i++) {
    const a = (i / 5) * Math.PI * 2 + 0.3;
    inner.push(<circle key={i} cx={Math.cos(a) * r * 0.30} cy={Math.sin(a) * r * 0.30} r={r * 0.35} fill={f.head} />);
  }
  return (
    <g transform={`translate(${x} ${y}) scale(${scale})`}>
      <g opacity="0.95">{outer}</g>
      <g>{inner}</g>
      <circle cx="0" cy="0" r={r * 0.24} fill={f.center} />
    </g>
  );
}

// Where stems gather. Paper wraps (kraft/silk) form a cone whose front fold
// covers from ~y296 down, so stems originate at PAPER and their cut ends hide
// inside the cone. Twine is a bare hand-tied bunch — there's no vase, so the
// stems pass through the tie (~y320) and their cut ends show BELOW it.
const STEM_BASE_PAPER = 318;
const STEM_BASE_TWINE = 360;
// Flower heads are anchored to this line regardless of wrap, so switching wrap
// only changes how the stems are gathered at the bottom, not the silhouette.
const HEAD_ANCHOR = STEM_BASE_PAPER;

function Stem({ type, index, total, isNew, wrap }) {
  const { x, angle, height } = stemPlacement(index, total);
  const baseY = wrap === 'twine' ? STEM_BASE_TWINE : STEM_BASE_PAPER;
  // extend the drawn length downward for twine so the head stays put
  const h = height + (baseY - HEAD_ANCHOR);
  const fadeRef = React.useRef(null);
  React.useEffect(() => {
    if (!fadeRef.current) return;
    if (isNew) {
      fadeRef.current.style.transformOrigin = `${x + 160}px ${baseY}px`;
      fadeRef.current.animate(
        [
          { transform: 'translateY(20px) scale(.7) rotate(-2deg)', opacity: 0 },
          { transform: 'translateY(0) scale(1) rotate(0)', opacity: 1 },
        ],
        { duration: 460, easing: 'cubic-bezier(.2,.8,.2,1)', fill: 'both' }
      );
    }
  }, []);
  return (
    <g ref={fadeRef}>
      <g transform={`translate(${x + 160} ${baseY}) rotate(${angle})`}>
        {/* stem */}
        <path d={`M0 0 Q ${jitter(index, 5, 3)} ${-h / 2} ${jitter(index, 6, 2)} ${-h}`}
              stroke="#6e8c63" strokeWidth="1.8" fill="none" strokeLinecap="round" />
        {/* leaf */}
        {Math.abs(jitter(index, 7, 1)) > .3 && (
          <ellipse cx={jitter(index, 8, 6) - 4} cy={-h / 2 - 10} rx="7" ry="3" fill="#6e8c63"
                   transform={`rotate(${jitter(index, 9, 30) - 25} ${jitter(index, 8, 6) - 4} ${-h / 2 - 10})`} />
        )}
        {/* flower head */}
        <Flower type={type} x={jitter(index, 6, 2)} y={-h}
                scale={0.9 + Math.abs(jitter(index, 10, 0.15))} />
      </g>
    </g>
  );
}

// Wraps: kraft cone, silk ribbon band, twine knot
function Wrap({ style = 'kraft' }) {
  if (style === 'kraft') {
    return (
      <g>
        {/* back layer — curved cone */}
        <path d="M 70 282 Q 60 320 100 380 Q 130 396 160 396 Q 190 396 220 380 Q 260 320 250 282 Q 245 286 230 290 Q 195 296 160 296 Q 125 296 90 290 Q 75 286 70 282 Z"
              fill="#d4ac80" stroke="#8d6238" strokeWidth="1.2" />
        {/* front overlap — paper folded in front */}
        <path d="M 100 296 Q 90 330 125 392 Q 142 400 160 400 Q 178 400 195 392 Q 230 330 220 296 Q 210 308 195 320 Q 178 330 160 330 Q 142 330 125 320 Q 110 308 100 296 Z"
              fill="#c8a070" stroke="#8d6238" strokeWidth="1" opacity="0.95" />
        {/* paper crease lines — gentle */}
        <path d="M 110 300 Q 130 350 145 392" stroke="#8d6238" strokeWidth=".5" fill="none" opacity=".4" />
        <path d="M 210 300 Q 190 350 175 392" stroke="#8d6238" strokeWidth=".5" fill="none" opacity=".4" />
        <path d="M 160 300 V 392" stroke="#8d6238" strokeWidth=".4" opacity=".25" />
        {/* twine tie */}
        <ellipse cx="160" cy="320" rx="62" ry="5" fill="#7a5a3a" />
        <path d="M 160 320 L 150 338 M 160 320 L 170 338" stroke="#7a5a3a" strokeWidth="1.5" strokeLinecap="round" />
      </g>
    );
  }
  if (style === 'silk') {
    return (
      <g>
        {/* curved silk wrap, back layer */}
        <path d="M 80 282 Q 70 322 110 380 Q 135 396 160 396 Q 185 396 210 380 Q 250 322 240 282 Q 235 286 220 290 Q 188 296 160 296 Q 132 296 100 290 Q 85 286 80 282 Z"
              fill="#f1e9d4" stroke="#a8606a" strokeWidth="1" opacity=".95" />
        {/* front overlap */}
        <path d="M 105 296 Q 95 332 130 390 Q 145 398 160 398 Q 175 398 190 390 Q 225 332 215 296 Q 205 308 190 318 Q 175 326 160 326 Q 145 326 130 318 Q 115 308 105 296 Z"
              fill="#eddfc6" stroke="#a8606a" strokeWidth=".8" opacity=".95" />
        {/* silk ribbon band */}
        <rect x="90" y="310" width="140" height="18" fill="#c45c6e" rx="2" />
        <path d="M 90 310 L 80 304 L 78 326 L 90 328 Z" fill="#a8606a" />
        <path d="M 230 310 L 240 304 L 242 326 L 230 328 Z" fill="#a8606a" />
        {/* ribbon shine */}
        <rect x="92" y="313" width="136" height="3" fill="#e88394" opacity=".5" />
      </g>
    );
  }
  // twine — bare hand-tied
  return (
    <g>
      {/* faint paper hint behind stems */}
      <path d="M 105 282 Q 95 322 130 380 Q 145 392 160 392 Q 175 392 190 380 Q 225 322 215 282"
            fill="none" stroke="#6e8c63" strokeWidth=".5" opacity=".4" />
      {/* twine wrap */}
      <ellipse cx="160" cy="320" rx="52" ry="10" fill="#b69968" />
      <path d="M 108 320 Q 160 312 212 320 Q 160 328 108 320 Z" fill="#9d8350" opacity=".7" />
      <ellipse cx="160" cy="320" rx="52" ry="10" fill="none" stroke="#7a5a3a" strokeWidth="1" />
      <path d="M 115 318 L 110 340 L 118 342" stroke="#7a5a3a" strokeWidth="1.6" fill="none" strokeLinecap="round" />
      <path d="M 205 318 L 210 340 L 202 342" stroke="#7a5a3a" strokeWidth="1.6" fill="none" strokeLinecap="round" />
    </g>
  );
}

function Bouquet({ stems, wrap, accent }) {
  // sort stems so taller flowers render behind (smaller t = center)
  const ordered = stems.map((s, i) => ({ ...s, i })).sort((a, b) => {
    const ai = Math.abs(a.i / Math.max(1, stems.length - 1) - 0.5);
    const bi = Math.abs(b.i / Math.max(1, stems.length - 1) - 0.5);
    return bi - ai;
  });
  return (
    <svg viewBox="0 0 320 420" width="100%" style={{ display: 'block' }}>
      <defs>
        <radialGradient id="bouquet-shadow" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor="rgba(60,40,20,.22)" />
          <stop offset="100%" stopColor="rgba(60,40,20,0)" />
        </radialGradient>
      </defs>
      {/* ground shadow */}
      <ellipse cx="160" cy="402" rx="100" ry="10" fill="url(#bouquet-shadow)" />
      {/* back stems first (sorted: outer first) */}
      {ordered.map(s => (
        <Stem key={s.id} type={s.type} index={s.i} total={stems.length} isNew={s.isNew} wrap={wrap} />
      ))}
      <Wrap style={wrap} />
    </svg>
  );
}

// Export to global
Object.assign(window, { Bouquet, FLOWERS });
