import React, { useMemo } from "react";
import {
  AbsoluteFill,
  Img,
  interpolate,
  useCurrentFrame,
  useVideoConfig,
} from "remotion";

const rainbowColors = [
  "#FF6B6B", // Red-ish
  "#FFD93D", // Yellow
  "#6BCB77", // Green
  "#4D96FF", // Blue
  "#9D4EDD", // Purple
  "#FF6EC7", // Pink
];

type LayoutType =
  | "left-diagonal"
  | "right-diagonal"
  | "vertical"
  | "horizontal"
  | "swirl";

export const SceneImageWithRainbowText: React.FC<{
  backgroundImage?: string;
  words: { text: string; delay: number }[];
  duration: number;
  layout?: LayoutType;
  imageAnimation?:
    | "zoomIn"
    | "zoomOut"
    | "rolling"
    | "pulse"
    | "fade"
    | "pan"
    | "kenBurns"
    | null;
}> = ({
  backgroundImage,
  words,
  duration,
  layout = "right-diagonal",
  imageAnimation = null,
}) => {
  const frame = useCurrentFrame();
  const { fps, width, height } = useVideoConfig();

  const middleIndex = Math.floor(words.length / 2);
  const spacing = 100; // base spacing for layout
  const padding = 100; // safety padding from edges

  /**
   * Memoised function that constrains a word's top‑left corner so the entire
   * box stays inside the padded safe area.
   */
  const constrainPosition = useMemo(
    () =>
      (
        x: number,
        y: number,
        wordWidth: number,
        wordHeight: number,
      ): { x: number; y: number } => {
        const safeLeft = padding;
        const safeRight = width - padding - wordWidth;
        const safeTop = padding;
        const safeBottom = height - padding - wordHeight;

        return {
          x: Math.min(Math.max(x, safeLeft), safeRight),
          y: Math.min(Math.max(y, safeTop), safeBottom),
        };
      },
    [width, height, padding],
  );

  // Add image animation styles
  const imageStyle: React.CSSProperties = {
    position: "absolute",
    width: "100%",
    height: "100%",
    objectFit: "cover",
  };

  if (imageAnimation === "zoomIn") {
    const scale = interpolate(frame, [0, 100], [1, 1.2], {
      extrapolateRight: "clamp",
    });
    imageStyle.transform = `scale(${scale})`;
  } else if (imageAnimation === "zoomOut") {
    const scale = interpolate(frame, [0, 100], [1.2, 1], {
      extrapolateRight: "clamp",
    });
    imageStyle.transform = `scale(${scale})`;
  } else if (imageAnimation === "rolling") {
    const rotate = interpolate(frame, [0, 100], [0, 360]);
    imageStyle.transform = `rotate(${rotate}deg)`;
  } else if (imageAnimation === "pulse") {
    const scale = interpolate(frame % 60, [0, 30, 60], [1, 1.05, 1], {
      extrapolateRight: "clamp",
    });
    imageStyle.transform = `scale(${scale})`;
  } else if (imageAnimation === "fade") {
    const opacity = interpolate(frame, [0, 20], [0, 1], {
      extrapolateRight: "clamp",
    });
    imageStyle.opacity = opacity;
  } else if (imageAnimation === "pan") {
    const translateX = interpolate(frame, [0, 100], [0, -50], {
      extrapolateRight: "clamp",
    });
    imageStyle.transform = `translateX(${translateX}px)`;
    imageStyle.width = "120%"; // Make image wider to allow for panning
  } else if (imageAnimation === "kenBurns") {
    const scale = interpolate(frame, [0, 100], [1, 1.2], {
      extrapolateRight: "clamp",
    });
    const translateX = interpolate(frame, [0, 100], [0, -50], {
      extrapolateRight: "clamp",
    });
    const translateY = interpolate(frame, [0, 100], [0, -30], {
      extrapolateRight: "clamp",
    });
    imageStyle.transform = `scale(${scale}) translate(${translateX}px, ${translateY}px)`;
    imageStyle.width = "120%";
    imageStyle.height = "120%";
  }

  return (
    <AbsoluteFill
      style={{
        justifyContent: "center",
        alignItems: "center",
        position: "relative",
        fontFamily: "Arial, sans-serif",
        backgroundColor: "black", // Black background as fallback
      }}
    >
      {/* Background image - only rendered if provided */}
      {backgroundImage && <Img src={backgroundImage} style={imageStyle} />}

      {/* Words */}
      <div style={{ position: "relative", width: "100%", height: "100%" }}>
        {words.map((word, index) => {
          const wordDelayFrames = word.delay * fps;
          const appearStart = wordDelayFrames;
          const appearEnd = wordDelayFrames + 10; // ≈0.5 s at 30 fps

          const opacity = interpolate(frame, [appearStart, appearEnd], [0, 1], {
            extrapolateLeft: "clamp",
            extrapolateRight: "clamp",
          });

          const scale = interpolate(frame, [appearStart, appearEnd], [0.8, 1], {
            extrapolateLeft: "clamp",
            extrapolateRight: "clamp",
          });

          const offsetFromMiddle = index - middleIndex;

          // Rough size estimate (good enough for boundary clamping)
          const estWidth = word.text.length * 40 + 64;
          const estHeight = 120;

          // Base position before constraining
          let baseX = 0;
          let baseY = 0;

          switch (layout) {
            case "right-diagonal":
              baseX = width / 2 + offsetFromMiddle * spacing * 1.2;
              baseY = height / 2 + offsetFromMiddle * spacing;
              break;
            case "left-diagonal":
              baseX = width / 2 - offsetFromMiddle * spacing * 1.2;
              baseY = height / 2 + offsetFromMiddle * spacing;
              break;
            case "vertical":
              baseX = width / 2;
              baseY = height / 2 + offsetFromMiddle * spacing * 2;
              break;
            case "horizontal":
              baseX = width / 2 + offsetFromMiddle * spacing;
              baseY = height / 2;
              break;
            case "swirl":
              const angle = offsetFromMiddle * Math.PI * 0.5;
              const radius = spacing * Math.abs(offsetFromMiddle);
              baseX = width / 2 + Math.cos(angle) * radius;
              baseY = height / 2 + Math.sin(angle) * radius;
              break;
            default:
              baseX = width / 2 + offsetFromMiddle * spacing * 1.2;
              baseY = height / 2 + offsetFromMiddle * spacing;
          }

          // Centre the word box around its base position
          const adjustedX = baseX - estWidth / 2;
          const adjustedY = baseY - estHeight / 2;

          // Keep inside safe area
          const { x: cx, y: cy } = constrainPosition(
            adjustedX,
            adjustedY,
            estWidth,
            estHeight,
          );

          // Round to full pixels to prevent sub‑pixel flicker
          const left = Math.round(cx);
          const top = Math.round(cy);

          return (
            <div
              key={index}
              style={{
                position: "absolute",
                top,
                left,
                transform: `scale(${scale})`,
                opacity,
                backgroundColor: "black",
                color: rainbowColors[index % rainbowColors.length],
                borderRadius: "16px",
                padding: "16px 32px",
                fontSize: "84px",
                fontWeight: "bold",
                whiteSpace: "nowrap",
                transformOrigin: "center",
              }}
            >
              {word.text}
            </div>
          );
        })}
      </div>
    </AbsoluteFill>
  );
};
