// @ts-nocheck
// ============================================================================
// MOTION GRAPHICS · OBSIDIAN ORBIT — Scene 09 / DROP THE SCRIPT  (11s, 330f)
//
// "Keynote object-worship". ONE hero artifact: the EPISODE-FOLDER slab — a thick
// glass slab whose FACE is an episode workspace (a folder header + an empty
// dropzone). A raw ".txt" script card DROPS onto its face from above and docks
// with a pop; a scan-line then SWEEPS across the text as the UI reads it,
// lighting each line in turn; a READY check pulses on once the read completes.
// The WORLD orbits (never the camera) in slow hold→ease arcs; spec Callouts
// billboard on drawn leader lines at waypoints ("DROP SCRIPT", "AUTO-READ");
// the angle-tracked sheen rakes the turn. A riser builds into the settle where
// the slab LOCKS straight-on with an impact + shockwave as the ready-check
// lands — the payoff — then idles, sheen tracking the final turn.
//
// Built ENTIRELY on the Plinth module (mirrors ObsidianOrbit.tsx's contract) +
// the shared Chronixel engine. CSS-3D only, deterministic, no WebGL.
// ============================================================================
import React from "react";
import { AbsoluteFill, useCurrentFrame, useVideoConfig } from "remotion";

import {
  Plinth,
  OrbitWorld,
  Extrude,
  Callout,
  DustMotes,
} from "../../plinth/plinth";
import { C, withAlpha, ACCENT_GRAD } from "../../chronixel/theme";
import { FONT, MONO } from "../../chronixel/fonts";
import {
  beat,
  clamp01,
  mix,
  osc,
  enter,
  springAt,
  EASE,
  SPRING,
} from "../../chronixel/motion";
import { Shockwave, GlowPulse, LightSweep } from "../../chronixel/fx";

/* ----------------------------------------------------------------------------
   A small mono eyebrow tag pinned top-left over the void — frames the beat.
   -------------------------------------------------------------------------- */
const Eyebrow: React.FC<{ at: number; children: React.ReactNode }> = ({
  at,
  children,
}) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  return (
    <div
      style={{
        position: "absolute",
        left: 120,
        top: 120,
        display: "flex",
        alignItems: "center",
        gap: 14,
        fontFamily: MONO,
        fontSize: 15,
        letterSpacing: 5,
        textTransform: "uppercase",
        color: C.accent2,
        ...enter(frame, fps, at, { from: "left", dist: 32, blur: 0 }),
      }}
    >
      <span
        style={{
          width: 30,
          height: 2,
          background: ACCENT_GRAD,
          boxShadow: `0 0 12px ${C.accentGlow}`,
        }}
      />
      {children}
    </div>
  );
};

/* ============================================================================
   DROP THE SCRIPT.  Hero = the EPISODE-FOLDER artifact. A raw .txt card drops
   onto the slab face, a scan-line reads the text line-by-line, a ready-check
   pulses on. The world orbits in, callouts fire, then the slab LOCKS front-on
   with an impact as the read completes.
   ========================================================================== */
export const MgOrbitScene09DropScript: React.FC = () => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const t = frame / fps;

  const LOCK = 8.0; // the settle / payoff beat (seconds)

  // --- face choreography -------------------------------------------------
  const folderP = beat(frame, fps, 0.5, 1.6, EASE.out); // workspace fades in
  const DROP = 2.4; // the .txt card docks onto the face (seconds)
  const dropSpring = springAt(frame, fps, DROP, SPRING.SNAPPY); // card settle
  const dropIn = clamp01((t - (DROP - 0.7)) / 0.7); // card travel/visibility
  const dropY = mix(-360, 0, clamp01(dropSpring)); // falls from above to dock
  const dropScale = mix(1.12, 1, clamp01(dropSpring)); // slight overshoot

  // scan-line read: sweeps top→bottom across the docked card's text.
  const SCAN_START = 3.3;
  const SCAN_END = 6.0;
  const scanP = beat(frame, fps, SCAN_START, SCAN_END, EASE.inOut); // 0→1 sweep

  // ready-check: pulses on once the read finishes, lands hard on the lock.
  const checkSpring = springAt(frame, fps, LOCK, SPRING.HEAVY); // weighty pop-in
  const checkP = clamp01(checkSpring);
  const checkPulse = 0.5 + 0.5 * osc(t, 2.2);

  // --- the lock-in: a weighty spring settle on the payoff -----------------
  const stamp = springAt(frame, fps, LOCK, SPRING.HEAVY); // 0→1 weighty settle
  const stampScale = mix(1.1, 1, clamp01(stamp)); // slams down to rest
  const flash = clamp01(1 - (t - LOCK) / 0.45) * (t >= LOCK ? 1 : 0);
  const riser = beat(frame, fps, LOCK - 1.4, LOCK, EASE.out); // build into apex
  const ringPulse = 0.5 + 0.5 * osc(t, 3);

  // hold→ease orbit so the slab reads its face on the way in, then a final arc
  // that settles to centre (0°) right at the lock — the snap-to-camera payoff.
  const legs = [
    { arc: -18, hold: 0.6, travel: 2.6 },
    { arc: 26, hold: 1.2, travel: 2.8 },
    { arc: -8, hold: 0.5, travel: 1.8 }, // lands ~0° near LOCK
  ];

  // the script card's text lines — each lights as the scan-line crosses it.
  const scriptLines = [0.9, 0.66, 0.84, 0.5, 0.74, 0.58];

  const HeroFace = (
    <div
      style={{
        position: "absolute",
        inset: 0,
        padding: 36,
        display: "flex",
        flexDirection: "column",
        gap: 18,
        transform: `scale(${stampScale})`,
      }}
    >
      {/* episode folder header — the workspace identity */}
      <div
        style={{
          display: "flex",
          alignItems: "center",
          gap: 14,
          opacity: folderP,
        }}
      >
        {/* folder glyph */}
        <div
          style={{
            position: "relative",
            width: 44,
            height: 34,
            borderRadius: 6,
            background: `linear-gradient(135deg, ${withAlpha(
              C.accent2,
              0.85,
            )}, ${C.accentDeep})`,
            boxShadow: `0 0 18px ${withAlpha(C.accent, 0.4)}`,
          }}
        >
          <div
            style={{
              position: "absolute",
              left: 4,
              top: -6,
              width: 20,
              height: 10,
              borderRadius: "5px 5px 0 0",
              background: withAlpha(C.accent2, 0.85),
            }}
          />
        </div>
        <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
          <div
            style={{
              fontFamily: MONO,
              fontSize: 12,
              letterSpacing: 3,
              textTransform: "uppercase",
              color: C.textDim,
            }}
          >
            Episode 09
          </div>
          <div
            style={{
              fontFamily: FONT,
              fontWeight: 800,
              fontSize: 22,
              lineHeight: 1,
              letterSpacing: "-0.01em",
              color: C.text,
            }}
          >
            Motion Graphics
          </div>
        </div>
      </div>

      {/* the dropzone — where the .txt card docks */}
      <div
        style={{
          position: "relative",
          flex: 1,
          borderRadius: 16,
          border: `1.5px dashed ${withAlpha(
            C.accent,
            mix(0.5, 0.18, clamp01(dropSpring)),
          )}`,
          background: withAlpha("#070a11", 0.5),
          overflow: "hidden",
          opacity: folderP,
        }}
      >
        {/* idle dropzone hint — fades as the card arrives */}
        <div
          style={{
            position: "absolute",
            inset: 0,
            display: "flex",
            alignItems: "center",
            justifyContent: "center",
            fontFamily: MONO,
            fontSize: 13,
            letterSpacing: 4,
            textTransform: "uppercase",
            color: withAlpha(C.accent2, 0.6),
            opacity: clamp01(1 - dropIn * 1.4),
          }}
        >
          drop .txt here
        </div>

        {/* the raw .txt script card — falls in and docks */}
        <div
          style={{
            position: "absolute",
            inset: 16,
            borderRadius: 12,
            background: `linear-gradient(135deg, ${withAlpha(
              "#0e1320",
              0.96,
            )}, ${withAlpha("#070a11", 0.96)})`,
            border: `1px solid ${withAlpha(C.accent, 0.4)}`,
            boxShadow: `0 18px 50px ${withAlpha("#000", 0.6)}, 0 0 24px ${withAlpha(
              C.accent,
              0.2 * dropIn,
            )}`,
            padding: 18,
            display: "flex",
            flexDirection: "column",
            gap: 13,
            opacity: dropIn,
            transform: `translateY(${dropY.toFixed(1)}px) scale(${dropScale.toFixed(
              3,
            )})`,
          }}
        >
          {/* card filename */}
          <div
            style={{
              display: "flex",
              alignItems: "center",
              gap: 8,
              fontFamily: MONO,
              fontSize: 12,
              letterSpacing: 2.5,
              textTransform: "uppercase",
              color: C.accent2,
            }}
          >
            <span
              style={{
                width: 18,
                height: 22,
                borderRadius: 3,
                border: `1px solid ${withAlpha(C.accent2, 0.6)}`,
                display: "inline-block",
              }}
            />
            script.txt
          </div>

          {/* the text lines — each lights as the scan-line passes it */}
          <div
            style={{
              position: "relative",
              flex: 1,
              display: "flex",
              flexDirection: "column",
              gap: 11,
              justifyContent: "center",
            }}
          >
            {scriptLines.map((w, i) => {
              const lineFrac = (i + 0.5) / scriptLines.length;
              const read = clamp01((scanP - lineFrac) * 6 + 1); // lit once passed
              return (
                <div
                  key={i}
                  style={{
                    height: 9,
                    width: `${w * 100}%`,
                    borderRadius: 5,
                    background:
                      read > 0.01
                        ? `linear-gradient(90deg, ${withAlpha(
                            C.accent2,
                            mix(0.2, 0.85, read),
                          )}, ${withAlpha("#ffffff", mix(0.1, 0.35, read))})`
                        : withAlpha("#ffffff", 0.18),
                    boxShadow:
                      read > 0.4
                        ? `0 0 12px ${withAlpha(C.accent, 0.4 * read)}`
                        : "none",
                  }}
                />
              );
            })}

            {/* the scan-line sweeping down the text as the UI reads it */}
            <div
              style={{
                position: "absolute",
                left: -6,
                right: -6,
                top: `${(scanP * 100).toFixed(1)}%`,
                height: 2,
                transform: "translateY(-1px)",
                background: `linear-gradient(90deg, transparent, ${C.accent2}, transparent)`,
                boxShadow: `0 0 16px ${C.accentGlow}`,
                opacity:
                  scanP > 0.001 && scanP < 0.999
                    ? 1
                    : clamp01((t - SCAN_START) / 0.2) *
                      clamp01((SCAN_END + 0.15 - t) / 0.2),
              }}
            />
          </div>

          {/* read-progress bar at the card's foot */}
          <div
            style={{
              height: 4,
              borderRadius: 2,
              background: withAlpha("#ffffff", 0.08),
              overflow: "hidden",
            }}
          >
            <div
              style={{
                height: "100%",
                width: `${(scanP * 100).toFixed(1)}%`,
                background: ACCENT_GRAD,
                boxShadow: `0 0 10px ${C.accentGlow}`,
              }}
            />
          </div>
        </div>

        {/* the READY check — pulses on once the read completes */}
        <div
          style={{
            position: "absolute",
            right: 16,
            bottom: 16,
            display: "flex",
            alignItems: "center",
            gap: 10,
            padding: "8px 14px 8px 10px",
            borderRadius: 999,
            background: withAlpha("#070a11", 0.85),
            border: `1px solid ${withAlpha(
              C.accent,
              0.4 + 0.4 * checkPulse,
            )}`,
            boxShadow: `0 0 ${(18 + 14 * checkPulse).toFixed(
              0,
            )}px ${withAlpha(C.accent, 0.35 * checkP * checkPulse)}`,
            opacity: checkP,
            transform: `scale(${mix(0.7, 1, checkP)})`,
          }}
        >
          <div
            style={{
              width: 26,
              height: 26,
              borderRadius: "50%",
              background: ACCENT_GRAD,
              display: "flex",
              alignItems: "center",
              justifyContent: "center",
              boxShadow: `inset 0 0 10px ${withAlpha("#ffffff", 0.4)}`,
            }}
          >
            {/* check mark */}
            <svg width="15" height="15" viewBox="0 0 15 15">
              <path
                d="M3 8 L6.2 11 L12 4"
                fill="none"
                stroke="#1a0d03"
                strokeWidth="2.4"
                strokeLinecap="round"
                strokeLinejoin="round"
                style={{
                  strokeDasharray: 20,
                  strokeDashoffset: mix(20, 0, checkP),
                }}
              />
            </svg>
          </div>
          <span
            style={{
              fontFamily: MONO,
              fontSize: 12,
              letterSpacing: 3,
              textTransform: "uppercase",
              color: C.text,
            }}
          >
            Ready
          </span>
        </div>
      </div>

      {/* the lock ring that snaps tight on the payoff beat */}
      <div
        style={{
          position: "absolute",
          inset: 18,
          borderRadius: 26,
          border: `2px solid ${withAlpha(C.accent, 0.28 + 0.42 * ringPulse)}`,
          opacity: clamp01(stamp),
          boxShadow: `0 0 30px ${withAlpha(C.accent, 0.3 * ringPulse)}`,
          pointerEvents: "none",
        }}
      />
    </div>
  );

  return (
    <Plinth>
      <Eyebrow at={0.3}>Drop The Script</Eyebrow>

      {/* riser glow swelling behind the hero into the payoff */}
      <AbsoluteFill style={{ pointerEvents: "none", zIndex: 1 }}>
        <GlowPulse
          size={1000}
          color={withAlpha(C.accent, 0.1 * riser)}
          strength={riser}
        />
      </AbsoluteFill>

      {/* impact flash + shockwave on the ready/lock payoff */}
      <AbsoluteFill style={{ pointerEvents: "none", zIndex: 6 }}>
        <GlowPulse
          size={1200}
          color={withAlpha(C.accent, 0.2 * flash)}
          strength={flash}
        />
        <Shockwave at={LOCK} size={820} />
        <Shockwave at={LOCK + 0.08} size={1120} />
        <LightSweep at={LOCK} dur={1.0} strength={0.16} />
      </AbsoluteFill>

      <OrbitWorld legs={legs} perspective={2300} bobAmp={12}>
        <DustMotes layers={3} opacity={0.42} />

        <Extrude w={720} h={460} depth={22} layers={16} radius={28}>
          {HeroFace}
        </Extrude>

        {/* billboarded spec callouts firing at orbit waypoints */}
        <Callout
          title="The Input"
          value="DROP SCRIPT"
          at={fps * (DROP + 0.2)}
          x={0}
          y={-310}
          leader={120}
          side="right"
        />
        <Callout
          title="The Engine"
          value="AUTO-READ"
          at={fps * (SCAN_START + 0.6)}
          x={460}
          y={120}
          leader={150}
          side="right"
        />
        <Callout
          title="The Output"
          value="READY"
          at={fps * (LOCK + 0.3)}
          x={-470}
          y={140}
          leader={160}
          side="left"
        />
      </OrbitWorld>

      {/* flat masked mirror sibling — re-renders the hero, simplified & matte */}
      <Plinth.Reflection>
        <Extrude w={720} h={460} depth={22} layers={10} radius={28} sheen={false}>
          {HeroFace}
        </Extrude>
      </Plinth.Reflection>
    </Plinth>
  );
};

export default MgOrbitScene09DropScript;