import React from "react";
import {
  AbsoluteFill,
  Img,
  interpolate,
  spring,
  useCurrentFrame,
  useVideoConfig,
  Easing,
} from "remotion";
import { z } from "zod";
import { colorSchema } from "../lib/branding";
import { FONT } from "../lib/fonts";
import { useLayout } from "../lib/aspect";
import { hexToRgba, mixHex, rand } from "../lib/anim";

export const glitterRevealSchema = z.object({
  brandText: z.string(),
  tagline: z.string(),
  /** Optional logo image URL. When empty the FlatRender brand mark is used. */
  logoUrl: z.string(),
  ...colorSchema,
});

type Props = z.infer<typeof glitterRevealSchema>;

// ── Default FlatRender brand mark (used when the user hasn't uploaded a logo) ──
const DefaultLogo: React.FC<{ size: number }> = ({ size }) => (
  <svg width={size} height={size} viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
    <rect width="48" height="48" rx="12" fill="#2563EB" />
    <rect x="16" y="13" width="3.6" height="22" rx="1.8" fill="white" />
    <rect x="16" y="13" width="16" height="3.6" rx="1.8" fill="white" />
    <rect x="16" y="22.2" width="11" height="3.6" rx="1.8" fill="white" fillOpacity="0.75" />
    <path d="M30 29L35.5 32L30 35Z" fill="white" fillOpacity="0.9" />
  </svg>
);

// Deterministic glitter field — each particle flies in from the edge, gathers at
// the logo, then disperses into an ambient orbit (the classic glitter-dust reveal).
const GLITTER = Array.from({ length: 150 }).map((_, i) => ({
  i,
  angleIn: rand(i) * Math.PI * 2,
  distIn: 520 + rand(i + 7) * 460,
  // gather target: a tight cluster over the logo
  tx: (rand(i + 11) - 0.5) * 360,
  ty: (rand(i + 19) - 0.5) * 240,
  // ambient orbit it settles into
  ambAngle: rand(i + 23) * Math.PI * 2,
  ambR: 230 + rand(i + 29) * 320,
  size: 1.6 + rand(i + 3) * 4.5,
  delay: (i % 18) * 0.9,
  speed: 0.4 + rand(i + 5) * 1.2,
}));

const Glitter: React.FC<{ accent: string; secondary: string; gold: string }> = ({
  accent,
  secondary,
  gold,
}) => {
  const frame = useCurrentFrame();
  const { width, height } = useVideoConfig();
  const L = useLayout();
  const cx = width / 2;
  const cy = height / 2;

  return (
    <AbsoluteFill>
      <svg width={width} height={height} style={{ overflow: "visible" }}>
        {GLITTER.map((p) => {
          const conv = interpolate(frame, [p.delay, p.delay + 34], [0, 1], {
            extrapolateLeft: "clamp",
            extrapolateRight: "clamp",
            easing: Easing.out(Easing.cubic),
          });
          const disp = interpolate(frame, [46, 86], [0, 1], {
            extrapolateLeft: "clamp",
            extrapolateRight: "clamp",
            easing: Easing.inOut(Easing.quad),
          });
          // start (far out) → gather cluster → ambient orbit
          const sx = cx + Math.cos(p.angleIn) * L.vmin(p.distIn);
          const sy = cy + Math.sin(p.angleIn) * L.vmin(p.distIn);
          const gx = cx + L.vmin(p.tx);
          const gy = cy + L.vmin(p.ty);
          const ax = cx + Math.cos(p.ambAngle + frame * 0.004 * p.speed) * L.vmin(p.ambR);
          const ay = cy + Math.sin(p.ambAngle + frame * 0.004 * p.speed) * L.vmin(p.ambR);
          const tgtX = gx + (ax - gx) * disp;
          const tgtY = gy + (ay - gy) * disp;
          const x = sx + (tgtX - sx) * conv;
          const y = sy + (tgtY - sy) * conv;

          const twinkle = 0.3 + 0.7 * Math.abs(Math.sin((frame + p.i * 13) / (6 + (p.i % 5))));
          const appear = interpolate(frame, [p.delay, p.delay + 10], [0, 1], { extrapolateRight: "clamp" });
          const c = p.i % 4 === 0 ? gold : p.i % 3 === 0 ? secondary : accent;
          const r = L.vmin(p.size) * (0.7 + conv * 0.5);
          return (
            <circle
              key={p.i}
              cx={x}
              cy={y}
              r={r}
              fill={c}
              opacity={twinkle * appear}
              style={{ filter: `drop-shadow(0 0 ${r * 2.6}px ${c})` }}
            />
          );
        })}
      </svg>
    </AbsoluteFill>
  );
};

export const GlitterReveal: React.FC<Props> = ({
  brandText,
  tagline,
  logoUrl,
  accentColor,
  secondaryColor,
  backgroundColor,
  textColor,
}) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const L = useLayout();
  const gold = "#fcd34d";

  // Logo reveal (the glitter gathers ~frame 44, then the logo emerges).
  const logoSpring = spring({ frame: frame - 42, fps, config: { damping: 13, stiffness: 95, mass: 0.9 } });
  const logoScale = interpolate(logoSpring, [0, 1], [0.55, 1]);
  const logoOpacity = interpolate(frame, [42, 60], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });

  // Bright convergence flash.
  const flash = interpolate(frame, [40, 47, 60], [0, 0.85, 0], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });

  // Core glow that breathes behind the logo.
  const glow = interpolate(frame, [44, 70], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
  const breathe = 1 + 0.05 * Math.sin(frame / 16);

  // Shine sweep across the logo at reveal.
  const sweepX = interpolate(frame, [58, 88], [-L.vmin(360), L.vmin(360)], { extrapolateLeft: "clamp", extrapolateRight: "clamp", easing: Easing.inOut(Easing.cubic) });
  const sweepOp = interpolate(frame, [58, 66, 82, 90], [0, 0.9, 0.9, 0], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });

  // Text.
  const brandY = interpolate(frame, [70, 92], [L.vmin(70), 0], { extrapolateLeft: "clamp", extrapolateRight: "clamp", easing: Easing.out(Easing.cubic) });
  const brandOpacity = interpolate(frame, [70, 90], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
  const tagOpacity = interpolate(frame, [92, 112], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });
  const tagSpacing = interpolate(frame, [92, 120], [L.vmin(14), L.vmin(6)], { extrapolateLeft: "clamp", extrapolateRight: "clamp" });

  const logoSize = L.vmin(240);
  const hasLogo = Boolean(logoUrl && logoUrl.trim().length > 0);

  return (
    <AbsoluteFill style={{ backgroundColor, fontFamily: FONT, direction: "rtl" }}>
      {/* Deep radial backdrop */}
      <AbsoluteFill style={{ background: `radial-gradient(circle at 50% 45%, ${hexToRgba(accentColor, 0.16)} 0%, ${hexToRgba(secondaryColor, 0.06)} 32%, ${backgroundColor} 66%)` }} />

      {/* Core glow */}
      <AbsoluteFill style={{ justifyContent: "center", alignItems: "center" }}>
        <div style={{ width: logoSize * 2.2 * glow * breathe, height: logoSize * 2.2 * glow * breathe, borderRadius: "50%", background: `radial-gradient(circle, ${hexToRgba(accentColor, 0.5)} 0%, ${hexToRgba(gold, 0.18)} 35%, transparent 70%)`, filter: `blur(${L.vmin(10)}px)` }} />
      </AbsoluteFill>

      <Glitter accent={accentColor} secondary={secondaryColor} gold={gold} />

      {/* Logo */}
      <AbsoluteFill style={{ justifyContent: "center", alignItems: "center" }}>
        <div style={{ transform: `scale(${logoScale})`, opacity: logoOpacity, filter: `drop-shadow(0 0 ${L.vmin(24)}px ${hexToRgba(accentColor, 0.7)})`, display: "flex", alignItems: "center", justifyContent: "center", width: logoSize, height: logoSize }}>
          {hasLogo ? (
            <Img src={logoUrl} style={{ maxWidth: logoSize, maxHeight: logoSize, objectFit: "contain" }} />
          ) : (
            <DefaultLogo size={logoSize} />
          )}
        </div>
      </AbsoluteFill>

      {/* Convergence flash */}
      <AbsoluteFill style={{ justifyContent: "center", alignItems: "center", pointerEvents: "none" }}>
        <div style={{ width: logoSize * 2.4, height: logoSize * 2.4, borderRadius: "50%", background: `radial-gradient(circle, ${hexToRgba("#ffffff", flash)} 0%, ${hexToRgba(gold, flash * 0.6)} 25%, transparent 60%)`, mixBlendMode: "screen" }} />
      </AbsoluteFill>

      {/* Shine sweep */}
      <AbsoluteFill style={{ justifyContent: "center", alignItems: "center", overflow: "hidden" }}>
        <div style={{ position: "absolute", width: L.vmin(140), height: logoSize * 1.4, transform: `translateX(${sweepX}px) rotate(18deg)`, background: `linear-gradient(90deg, transparent, ${hexToRgba(mixHex(textColor, gold, 0.4), 0.95)}, transparent)`, filter: `blur(${L.vmin(18)}px)`, opacity: sweepOp, mixBlendMode: "screen" }} />
      </AbsoluteFill>

      {/* Brand text + tagline */}
      <AbsoluteFill style={{ justifyContent: "flex-end", alignItems: "center", flexDirection: "column", paddingBottom: L.vmin(130) }}>
        <div style={{ transform: `translateY(${brandY}px)`, opacity: brandOpacity, fontWeight: 900, fontSize: L.vmin(82), color: textColor, textAlign: "center", textShadow: `0 0 ${L.vmin(16)}px ${hexToRgba(accentColor, 0.7)}` }}>
          {brandText}
        </div>
        <div style={{ marginTop: L.vmin(18), opacity: tagOpacity, fontWeight: 500, fontSize: L.vmin(26), letterSpacing: tagSpacing, color: hexToRgba(textColor, 0.8), textAlign: "center" }}>
          {tagline}
        </div>
      </AbsoluteFill>
    </AbsoluteFill>
  );
};
