// scenes.jsx — Serenoil bottle opening + pour animation.
//
// Timeline (total 12s):
//   0.0 – 2.5  Establishing shot — bottle drifts in, soft shadow grows
//   2.5 – 4.5  Cap lifts off (anticipation wiggle, then rises with follow-through)
//   4.5 – 5.5  Pipette revealed, lifts up out of bottle
//   5.5 – 9.5  Drops fall (3 droplets, staggered) — splash on surface, ripples
//   9.5 – 12   Cap descends back, tagline fades in

const STAGE_W = 1280;
const STAGE_H = 720;
const BG = '#e8dac6'; // matches the photo's beige

// Bottle anchor inside stage. Bottle SVG body 320×640. We'll position it slightly
// right-of-center so droplets have room to fall left of it (good composition).
const BOTTLE_X = STAGE_W / 2 - 160; // top-left of 320-wide body box
const BOTTLE_Y = 60;                // body top at y=60 in stage coords
// Cap rests on top of body. The body's neck rim is at y=125 in body coords,
// so cap-bottom should sit at stage y = BOTTLE_Y + 125 = 185.
// Cap SVG is 200 tall with cap-bottom at y≈186 → translate cap so its 186 lines up.
const CAP_REST_Y = BOTTLE_Y + 125 - 186; // -1 → cap top at this y
// Pipette: tube-top in pipette coords is y=0 (collar). When inserted, the
// collar should sit just under cap. Tip at y=210 in pipette coords. Tube length
// ~196. We want tip somewhere near oil surface inside the bottle — let's place
// pipette so its collar is at stage y = BOTTLE_Y + 130.
const PIPETTE_REST_Y = BOTTLE_Y + 130;
const PIPETTE_X = STAGE_W / 2 - 30;

// Surface where droplets land — a soft pool below the bottle's right side
const POOL_CX = STAGE_W / 2 + 170;
const POOL_CY = STAGE_H - 70;
// Pipette tip during pour (stage coords) — calculated from pipette transform
function pipetteTipPos(pipetteOffsetY, tilt) {
  // collar at (PIPETTE_X+30, PIPETTE_REST_Y + pipetteOffsetY)
  // tip is 210 below collar (along tilted axis)
  const collarX = PIPETTE_X + 30;
  const collarY = PIPETTE_REST_Y + pipetteOffsetY;
  const len = 210;
  const rad = (tilt * Math.PI) / 180;
  return {
    x: collarX + Math.sin(rad) * len,
    y: collarY + Math.cos(rad) * len,
  };
}

// — Backdrop: soft beige gradient with a subtle vignette and floor shadow —
function Backdrop() {
  return (
    <div style={{
      position: 'absolute', inset: 0,
      background: `radial-gradient(ellipse at 50% 35%, #f0e3cf 0%, ${BG} 45%, #d6c5a8 100%)`,
    }}>
      {/* Floor — subtle gradient suggesting a surface */}
      <div style={{
        position: 'absolute', left: 0, right: 0, bottom: 0,
        height: 220,
        background: 'linear-gradient(to bottom, rgba(0,0,0,0) 0%, rgba(80,55,30,0.10) 60%, rgba(60,40,20,0.22) 100%)',
      }}/>
      {/* horizon line */}
      <div style={{
        position: 'absolute', left: 0, right: 0, bottom: 220,
        height: 1, background: 'rgba(0,0,0,0.06)',
      }}/>
    </div>
  );
}

// — Bottle shadow on the floor — grows/shrinks subtly with cap motion —
function BottleShadow({ pulse = 0 }) {
  // pulse 0..1 — used to soften shadow when cap lifts
  const opacity = 0.32 - 0.05 * pulse;
  return (
    <div style={{
      position: 'absolute',
      left: STAGE_W / 2 - 140,
      top: STAGE_H - 110,
      width: 280, height: 36,
      borderRadius: '50%',
      background: `radial-gradient(ellipse at center, rgba(60,30,10,${opacity}) 0%, rgba(60,30,10,0) 70%)`,
      filter: 'blur(2px)',
    }}/>
  );
}

// — A single oil droplet falling from a fixed start to splash point —
// startTime: when it appears
// fromX,fromY → toX,toY in stage coords
function Droplet({ startTime, duration = 0.55, fromX, fromY, toX, toY, size = 14 }) {
  const time = useTime();
  const local = time - startTime;
  if (local < 0 || local > duration + 0.1) return null;

  // Stretch into teardrop while accelerating (gravity)
  const t = clamp(local / duration, 0, 1);
  const eased = t * t; // ease-in for gravity
  const x = fromX + (toX - fromX) * eased;
  const y = fromY + (toY - fromY) * eased;
  // Stretch
  const stretch = 1 + 0.9 * t;
  const squish = 1 - 0.25 * t;
  // Fade out at very end
  const opacity = local > duration ? 0 : 1;

  return (
    <div style={{
      position: 'absolute',
      left: x - size / 2,
      top: y - size / 2,
      width: size,
      height: size,
      transform: `scaleX(${squish}) scaleY(${stretch})`,
      transformOrigin: 'center',
      opacity,
      pointerEvents: 'none',
      filter: 'drop-shadow(0 2px 3px rgba(60,30,10,0.4))',
    }}>
      <svg viewBox="0 0 20 20" width={size} height={size} style={{ overflow: 'visible' }}>
        <defs>
          <radialGradient id={`dropG-${startTime}`} cx="0.4" cy="0.35" r="0.7">
            <stop offset="0"   stopColor="#fde0a8"/>
            <stop offset="0.4" stopColor="#e0a04a"/>
            <stop offset="1"   stopColor="#7a3a12"/>
          </radialGradient>
        </defs>
        <ellipse cx="10" cy="10" rx="7" ry="9" fill={`url(#dropG-${startTime})`}/>
        <ellipse cx="7" cy="6" rx="2" ry="3" fill="#fff" opacity="0.5"/>
      </svg>
    </div>
  );
}

// — Splash + ripple where a droplet lands —
function Splash({ startTime, x, y }) {
  const time = useTime();
  const local = time - startTime;
  if (local < 0 || local > 1.6) return null;

  // Concentric expanding rings
  const rings = [0, 0.18, 0.36];
  return (
    <>
      {/* small bounce blob */}
      {local < 0.4 && (
        <div style={{
          position: 'absolute',
          left: x - 8, top: y - 8 - local * 30,
          width: 12, height: 12,
          borderRadius: '50%',
          background: 'radial-gradient(circle at 35% 30%, #fde0a8, #b66a2a 70%, #7a3a12)',
          opacity: 1 - local / 0.4,
          transform: `scale(${1 - local / 0.4})`,
          pointerEvents: 'none',
        }}/>
      )}
      {/* pool blob (oil hitting surface) */}
      <div style={{
        position: 'absolute',
        left: x - 30, top: y - 4,
        width: 60, height: 10,
        borderRadius: '50%',
        background: 'radial-gradient(ellipse at center, #c07a32 0%, #8a4a18 60%, rgba(80,40,10,0) 100%)',
        opacity: clamp(local / 0.2, 0, 1) * (1 - clamp((local - 1.2) / 0.4, 0, 1)),
        transform: `scaleX(${clamp(local / 0.3, 0.3, 1) + local * 0.15})`,
        transformOrigin: 'center',
        pointerEvents: 'none',
        filter: 'blur(0.8px)',
      }}/>
      {/* expanding ripple rings */}
      {rings.map((delay, i) => {
        const rt = local - delay;
        if (rt < 0 || rt > 1.4) return null;
        const p = rt / 1.4;
        const r = 8 + p * 70;
        const op = (1 - p) * 0.7;
        return (
          <div key={i} style={{
            position: 'absolute',
            left: x - r, top: y - r * 0.25,
            width: r * 2, height: r * 0.5,
            borderRadius: '50%',
            border: '1.5px solid rgba(180,100,40,0.7)',
            opacity: op,
            pointerEvents: 'none',
          }}/>
        );
      })}
    </>
  );
}

// ── Main Scene ──────────────────────────────────────────────────────────────
function SerenoilScene() {
  const time = useTime();

  // — Cap motion —
  // 0..2.5: rest. 2.5..2.7: tiny anticipation downpress. 2.7..4.5: lift up.
  // 9.5..11.5: descend back onto bottle.
  const capLiftIn = animate({ from: 0, to: 1, start: 2.7, end: 4.3, ease: Easing.easeOutCubic });
  const capAnticip = animate({ from: 0, to: 1, start: 2.5, end: 2.7, ease: Easing.easeInOutSine });
  const capReturn = animate({ from: 0, to: 1, start: 9.5, end: 11.0, ease: Easing.easeInOutCubic });

  // capOffsetY: 0 = resting on bottle. Negative = lifted.
  let capOffsetY = 0;
  let capRotate = 0;
  if (time < 2.5) {
    // rest
  } else if (time < 2.7) {
    // anticipation: press down 4px and tilt
    capOffsetY = capAnticip(time) * 4;
    capRotate = capAnticip(time) * -3;
  } else if (time < 9.5) {
    // lifted high
    capOffsetY = -260 * capLiftIn(time);
    // small rotational sway during lift
    capRotate = -3 + 3 * capLiftIn(time) + Math.sin((time - 2.7) * 4) * 1.5 * (1 - capLiftIn(time));
    // After full lift, gentle bob
    if (time > 4.3) {
      capOffsetY += Math.sin((time - 4.3) * 2.5) * 3;
      capRotate += Math.sin((time - 4.3) * 1.8) * 1.2;
    }
  } else {
    // returning
    capOffsetY = -260 * (1 - capReturn(time));
    capRotate = 0;
  }

  // — Pipette motion — coupled to cap (the dropper IS attached to the cap), so
  // it lifts WITH the cap. But it also slides up out of the bottle revealing oil.
  // Use the same offset.
  const pipetteOffsetY = capOffsetY;
  // During the pour window (5.5–8.5), tilt pipette slightly to one side so drops
  // fall offset from the bottle.
  let pipetteTilt = 0;
  if (time > 5.5 && time < 9.0) {
    const t = clamp((time - 5.5) / 0.6, 0, 1);
    const ot = clamp((9.0 - time) / 0.6, 0, 1);
    pipetteTilt = 8 * Math.min(t, ot, 1);
  }

  // Tip position for droplet origin
  const tip = pipetteTipPos(pipetteOffsetY, pipetteTilt);

  // Droplet landing position — the pool to the right of the bottle
  const landX = POOL_CX;
  const landY = POOL_CY;

  // Droplet schedule — three drops staggered
  const droplets = [
    { start: 6.0, size: 16 },
    { start: 7.2, size: 18 },
    { start: 8.3, size: 14 },
  ];

  // Camera: very subtle zoom + drift to keep things alive
  const camScale = 1 + 0.04 * Easing.easeInOutSine(clamp(time / 12, 0, 1));
  const camY = -8 * Math.sin(time * 0.3);

  // Establishing fade-in of bottle from 0..1.2s
  const introOp = animate({ from: 0, to: 1, start: 0, end: 1.0, ease: Easing.easeOutCubic })(time);
  const introY = animate({ from: 24, to: 0, start: 0, end: 1.4, ease: Easing.easeOutCubic })(time);

  // Tagline — fade in last 2 seconds. Bottle slides left to make room beside it.
  const tagOp = animate({ from: 0, to: 1, start: 9.8, end: 10.8, ease: Easing.easeOutCubic })(time);
  const tagY = animate({ from: 14, to: 0, start: 9.8, end: 10.8, ease: Easing.easeOutCubic })(time);
  const bottleSlideX = animate({ from: 0, to: -260, start: 9.5, end: 11.0, ease: Easing.easeInOutCubic })(time);

  // Shadow pulses softer when cap lifts
  const capLifted = clamp(-capOffsetY / 260, 0, 1);

  return (
    <>
      <Backdrop />

      {/* Camera wrapper */}
      <div style={{
        position: 'absolute', inset: 0,
        transform: `translateY(${camY}px) scale(${camScale})`,
        transformOrigin: '50% 50%',
      }}>
        {/* Bottle group + shadow + droplets all shift left during outro
           so the tagline can occupy the right half of the frame. */}
        <div style={{
          position: 'absolute', inset: 0,
          transform: `translateX(${bottleSlideX}px)`,
        }}>
        <BottleShadow pulse={capLifted} />

        {/* Bottle group (intro animation) */}
        <div style={{
          position: 'absolute', inset: 0,
          opacity: introOp,
          transform: `translateY(${introY}px)`,
        }}>
          {/* Pipette — drawn BEHIND the bottle body so the tube is hidden
             behind the glass/label. Only the section that rises above the
             bottle neck (under the cap) is visible. */}
          <div style={{
            position: 'absolute',
            left: PIPETTE_X,
            top: PIPETTE_REST_Y + pipetteOffsetY,
            transformOrigin: '50% 0%',
            transform: `rotate(${pipetteTilt}deg)`,
            zIndex: 1,
            transition: 'none',
          }}>
            <Pipette oilLevel={0.7 - clamp((time - 6) / 4, 0, 1) * 0.35} />
          </div>

          {/* Bottle body — sits ABOVE the pipette */}
          <div style={{
            position: 'absolute',
            left: BOTTLE_X,
            top: BOTTLE_Y,
            zIndex: 2,
          }}>
            <BottleBody />
          </div>

          {/* Cap — drawn on top, slides up, carrying the pipette visually */}
          <div style={{
            position: 'absolute',
            left: BOTTLE_X,
            top: CAP_REST_Y + capOffsetY,
            transformOrigin: '50% 100%',
            transform: `rotate(${capRotate}deg)`,
            zIndex: 3,
            filter: time > 2.7 && time < 9.5 ? 'drop-shadow(0 12px 20px rgba(0,0,0,0.25))' : 'drop-shadow(0 4px 8px rgba(0,0,0,0.2))',
          }}>
            <BottleCap />
          </div>
        </div>

        {/* Droplets — render above bottle so they pass over the bottle silhouette as needed */}
        <div style={{ position: 'absolute', inset: 0, zIndex: 4 }}>
          {droplets.map((d, i) => (
            <React.Fragment key={i}>
              <Droplet
                startTime={d.start}
                duration={0.55}
                fromX={tip.x}
                fromY={tip.y}
                toX={landX}
                toY={landY}
                size={d.size}
              />
              <Splash
                startTime={d.start + 0.55}
                x={landX}
                y={landY}
              />
            </React.Fragment>
          ))}

          {/* "Hanging drop" at pipette tip while pouring — small bead growing then falling */}
          {droplets.map((d, i) => {
            const t = time - (d.start - 0.5);
            if (t < 0 || t > 0.5) return null;
            const grow = clamp(t / 0.5, 0, 1);
            const r = 4 + grow * 5;
            return (
              <div key={`bead-${i}`} style={{
                position: 'absolute',
                left: tip.x - r,
                top: tip.y - r,
                width: r * 2,
                height: r * 2 * (1 + grow * 0.4),
                borderRadius: '50%',
                background: 'radial-gradient(circle at 35% 30%, #fde0a8, #c07a32 60%, #7a3a12)',
                pointerEvents: 'none',
                filter: 'drop-shadow(0 1px 2px rgba(60,30,10,0.4))',
              }}/>
            );
          })}
        </div>

        {/* Pool of oil that grows on the surface as drops land */}
        <Pool time={time} />
        </div>
      </div>

      {/* Tagline — sits to the RIGHT of the (now slid-left) bottle */}
      <div style={{
        position: 'absolute',
        right: 110,
        top: '50%',
        width: 540,
        textAlign: 'left',
        opacity: tagOp,
        transform: `translateY(calc(-50% + ${tagY}px))`,
        pointerEvents: 'none',
      }}>
        <div style={{
          fontFamily: "'Cormorant Garamond', 'Playfair Display', Georgia, serif",
          fontSize: 96,
          fontWeight: 500,
          color: '#1f3a2e',
          letterSpacing: '-1.5px',
          lineHeight: 1,
        }}>
          Serenoil
        </div>
        <div style={{
          marginTop: 22,
          fontFamily: "'Inter', system-ui, sans-serif",
          fontSize: 15,
          fontWeight: 600,
          letterSpacing: '5px',
          color: '#1f3a2e',
          textTransform: 'uppercase',
          opacity: 0.75,
        }}>
          Pure Jojoba · For Hair &amp; Skin
        </div>
        <div style={{
          marginTop: 18,
          fontFamily: "'Cormorant Garamond', 'Playfair Display', Georgia, serif",
          fontSize: 32,
          fontWeight: 400,
          fontStyle: 'italic',
          letterSpacing: '1px',
          color: '#ffffff',
          textShadow: '0 1px 12px rgba(0,0,0,0.18)',
        }}>
          The Ultimate Glow
        </div>
      </div>

      {/* Frame label for comments */}
      <div data-screen-label={`t=${time.toFixed(1)}s`} style={{ display: 'none' }}/>
    </>
  );
}

// — Oil pool growing on the surface as drops accumulate —
function Pool({ time }) {
  // Each drop adds to pool size at its splash time
  const splashes = [6.55, 7.75, 8.85];
  let amount = 0;
  splashes.forEach((s) => {
    if (time > s) amount += clamp((time - s) / 0.4, 0, 1);
  });
  if (amount <= 0) return null;
  const w = 60 + amount * 60;
  const h = 14 + amount * 6;
  return (
    <div style={{
      position: 'absolute',
      left: POOL_CX - w / 2,
      top: POOL_CY - h / 2,
      width: w,
      height: h,
      borderRadius: '50%',
      background: 'radial-gradient(ellipse at 40% 35%, #e0a04a 0%, #a85a26 50%, #5a2a0a 90%)',
      boxShadow: '0 4px 12px rgba(60,30,10,0.5), inset 0 -2px 4px rgba(0,0,0,0.25), inset 0 2px 4px rgba(255,220,170,0.5)',
      pointerEvents: 'none',
    }}/>
  );
}

Object.assign(window, { SerenoilScene });
