import React from "react";
import {Easing, useCurrentFrame, useVideoConfig} from "remotion";

/** Seconds come from the current Remotion sequence; no wall-clock animation. */
export const useSeconds = () => useCurrentFrame() / useVideoConfig().fps;
export const easeOut = Easing.bezier(0.16, 1, 0.3, 1);
export const easeInOut = Easing.bezier(0.65, 0, 0.35, 1);
export const progress = (t: number, start: number, duration: number) => {
  if (!Number.isFinite(duration) || duration <= 0) throw new Error("Duration must be positive");
  return Math.max(0, Math.min(1, (t - start) / duration));
};

/** Preserves final word geometry while each word resolves from blur. */
export function BlurWords({text, at = 0, stagger = 0.07, duration = 0.55, blur = 8, style}: {
  text: string; at?: number; stagger?: number; duration?: number; blur?: number; style?: React.CSSProperties;
}) {
  const t = useSeconds();
  const words = text.trim().split(/\s+/);
  return <span style={{whiteSpace: "pre-wrap", ...style}}>{words.map((word, index) => {
    const p = easeOut(progress(t, at + index * stagger, duration));
    return <React.Fragment key={index}><span style={{display: "inline-block", opacity: p, filter: p < 1 ? `blur(${blur * (1 - p)}px)` : undefined}}>{word}</span>{index < words.length - 1 ? " " : ""}</React.Fragment>;
  })}</span>;
}

/** A fixed mask reveals its children; animate the children separately if needed. */
export function MaskReveal({children, at = 0, duration = 0.8, direction = "up", style}: {
  children: React.ReactNode; at?: number; duration?: number; direction?: "up" | "down" | "left" | "right"; style?: React.CSSProperties;
}) {
  const p = easeOut(progress(useSeconds(), at, duration));
  const hidden = `${(1 - p) * 100}%`;
  const inset = {up: `${hidden} 0 0 0`, down: `0 0 ${hidden} 0`, left: `0 0 0 ${hidden}`, right: `0 ${hidden} 0 0`}[direction];
  return <div style={{...style, clipPath: `inset(${inset})`}}>{children}</div>;
}

export type TerminalStep = {command: string; at: number; typeSeconds: number; lines: {text: string; after: number; positive?: boolean}[]};

/** One command event owns typing and its output; times are sequence-local seconds. */
export function TerminalScene({steps, title = "Product demo", accent = "#bcf269", style}: {
  steps: TerminalStep[]; title?: string; accent?: string; style?: React.CSSProperties;
}) {
  const t = useSeconds();
  const rows = steps.flatMap((step, index) => {
    if (step.at < 0 || step.typeSeconds <= 0 || step.lines.some(line => line.after < 0)) throw new Error("Invalid terminal timing");
    if (t < step.at) return [];
    const enteredAt = step.at + step.typeSeconds;
    const typed = Math.floor(step.command.length * progress(t, step.at, step.typeSeconds));
    return [<div key={`command-${index}`} style={{color: "#fafbf6", minHeight: 40, whiteSpace: "pre-wrap", overflowWrap: "anywhere"}}><span style={{color: accent}}>❯ </span>{step.command.slice(0, typed)}{t < enteredAt && <span style={{color: accent}}>▌</span>}</div>, ...step.lines.map((line, i) => {
      const appearAt = enteredAt + line.after;
      const p = easeOut(progress(t, appearAt, 0.25));
      return p === 0 ? null : <div key={`${index}-${i}`} style={{minHeight:40, opacity:p, transform:`translateY(${8 * (1-p)}px)`, color: line.positive ? accent : "#a8adb9"}}>{line.text}</div>;
    })];
  });
  return <div style={{background: "#14161c", border:"1px solid #ffffff20", borderRadius:20, overflow:"hidden", boxShadow:"0 28px 100px #00000030", ...style}}>
    <div style={{fontSize:16, color:"#969eac", padding:"18px 24px", borderBottom:"1px solid #ffffff15", display:"flex", alignItems:"center", gap:8}}><span style={{width:8,height:8,borderRadius:8,background:accent}}/><span>{title}</span></div>
    <div style={{padding:32, fontFamily:"ui-monospace, Menlo, monospace", fontSize:24, lineHeight:"40px"}}>{rows}</div>
  </div>;
}
