import React from "react";
import { AbsoluteFill, Audio, Sequence, staticFile, useVideoConfig } from "remotion";
import { z } from "zod";
import { colorSchema } from "../lib/branding";
import { FONT } from "../lib/fonts";
import { useLayout } from "../lib/aspect";
import { getBlock } from "../scenes/registry";
import { withDefaults, clampDuration } from "../scenes/types";
import { FinishPass, GRADE_FILTER } from "../scenes/chrome";

/**
 * FlexStory — the scene sequencer. A template is `scenes: SceneInstance[]`; this
 * composition stacks each block in a <Sequence> at its own (clamped) duration and
 * computes the total length dynamically via calculateMetadata. This is the engine
 * that turns add/duplicate/delete/reorder + per-scene duration into a real render.
 */
export const flexStorySchema = z.object({
  scenes: z.array(
    z.object({
      blockId: z.string(),
      durationSec: z.number(),
      props: z.record(z.string()),
    })
  ),
  // Audio (optional so the existing render binding doesn't need to send them).
  music: z.string().optional(), // path/url of the music bed; "" = silent
  musicVolume: z.number().optional(),
  sfx: z.boolean().optional(), // transition whoosh + outro chime
  ...colorSchema,
});
type Props = z.infer<typeof flexStorySchema>;

const FPS = 30;
const resolveAudio = (u: string) => (/^https?:\/\//.test(u) ? u : staticFile(u));

export const flexStoryDefaults: Props = {
  scenes: [
    { blockId: "TitleCard", durationSec: 4, props: { kicker: "فلت‌رندر", title: "موتور صحنه‌ای", subtitle: "هر قالب، فهرستی از صحنه‌های قابل‌ویرایش است" } },
    { blockId: "CharacterScene", durationSec: 3, props: { title: "یک ایده", caption: "همه‌چیز با یک جرقهٔ کوچک شروع شد", character: "illustrations/dicebear/openpeeps-04.svg", prop: "cup" } },
    { blockId: "ImageCaption", durationSec: 4, props: { title: "نمایش تصویر", caption: "تصویر یا اسکرین‌شات خود را اینجا قرار دهید", imageUrl: "" } },
    { blockId: "KineticQuote", durationSec: 5, props: { quote: "ساختن ویدیوی حرفه‌ای دیگر سخت نیست.", author: "فلت‌رندر" } },
    { blockId: "Slideshow", durationSec: 6, props: { title: "چرا فلت‌رندر؟", slide1: "سریع", slide2: "ارزان", slide3: "حرفه‌ای", slide4: "" } },
    { blockId: "OutroCTA", durationSec: 4, props: { brandText: "فلت‌رندر", tagline: "همین حالا داستان خود را بسازید", cta: "شروع کنید" } },
  ],
  accentColor: "#cf8a76",
  secondaryColor: "#6f9d96",
  backgroundColor: "#ece4d6",
  textColor: "#2b3a55",
  music: "audio/music-ambient.mp3",
  musicVolume: 0.6,
  sfx: true,
};

const activeScenes = (props: Props) =>
  (props.scenes?.length ? props.scenes : flexStoryDefaults.scenes).filter((s) => getBlock(s.blockId));

export const FlexStory: React.FC<Props> = (props) => {
  const { fps } = useVideoConfig();
  const L = useLayout();
  const colors = {
    accentColor: props.accentColor,
    secondaryColor: props.secondaryColor,
    backgroundColor: props.backgroundColor,
    textColor: props.textColor,
  };
  const scenes = activeScenes(props);
  const music = props.music === undefined ? "audio/music-ambient.mp3" : props.music;
  const musicVolume = props.musicVolume ?? 0.6;
  const sfx = props.sfx ?? true;

  // Precompute each scene's start frame + duration (shared by visuals + SFX).
  const starts: number[] = [];
  let acc = 0;
  const durations = scenes.map((sc) => {
    const dur = Math.round(clampDuration(sc.durationSec, getBlock(sc.blockId)!) * fps);
    starts.push(acc);
    acc += dur;
    return dur;
  });

  return (
    <AbsoluteFill style={{ backgroundColor: colors.backgroundColor, fontFamily: FONT, filter: GRADE_FILTER }}>
      {music ? <Audio src={resolveAudio(music)} loop volume={musicVolume} /> : null}

      {scenes.map((sc, i) => {
        const Comp = getBlock(sc.blockId)!.component;
        return (
          <Sequence key={i} from={starts[i]} durationInFrames={durations[i]}>
            <Comp data={withDefaults(getBlock(sc.blockId)!, sc.props || {})} colors={colors} L={L} index={i} total={scenes.length} durationInFrames={durations[i]} />
          </Sequence>
        );
      })}

      {/* Transition SFX: whoosh at each scene start, a chime on the final scene. */}
      {sfx
        ? scenes.map((_, i) => (
            <Sequence key={`sfx${i}`} from={starts[i]}>
              <Audio
                src={staticFile(i === scenes.length - 1 ? "audio/sfx-chime.mp3" : "audio/sfx-whoosh.mp3")}
                volume={0.5}
              />
            </Sequence>
          ))
        : null}

      {/* Cinematic finish over every scene — the shared quality floor. */}
      <FinishPass colors={colors} />
    </AbsoluteFill>
  );
};

/** Composition length = Σ per-scene durations (so add/delete/duration all flow). */
export const calcFlexStoryMetadata = ({ props }: { props: Props }) => {
  const total = activeScenes(props).reduce((acc, s) => {
    const b = getBlock(s.blockId)!;
    return acc + Math.round(clampDuration(s.durationSec, b) * FPS);
  }, 0);
  return { durationInFrames: Math.max(1, total) };
};
