import {
  DEFAULT_SCENE_ACCENT_COLOR,
  DEFAULT_SCENE_BACKGROUND_COLOR,
} from "@/lib/studio-color-palettes";
import type { Layer, Scene, SceneTransition } from "@/lib/studio-types";
import { DEFAULT_SCENE_DURATION } from "@/lib/studio-types";

const SCENE_TRANSITIONS: SceneTransition[] = [
  "none",
  "fade",
  "slide-left",
  "zoom",
];

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

function parseLayer(value: unknown): Layer | null {
  if (!isRecord(value)) return null;
  if (typeof value.id !== "string" || typeof value.type !== "string") return null;
  if (
    typeof value.x !== "number" ||
    typeof value.y !== "number" ||
    typeof value.width !== "number" ||
    typeof value.height !== "number"
  ) {
    return null;
  }
  return {
    id: value.id,
    type: value.type as Layer["type"],
    name: typeof value.name === "string" ? value.name : undefined,
    visible: typeof value.visible === "boolean" ? value.visible : undefined,
    x: value.x,
    y: value.y,
    width: value.width,
    height: value.height,
    rotation: typeof value.rotation === "number" ? value.rotation : 0,
    opacity: typeof value.opacity === "number" ? value.opacity : 1,
    zIndex: typeof value.zIndex === "number" ? value.zIndex : 0,
    props: isRecord(value.props) ? value.props : {},
  };
}

function parseScene(value: unknown): Scene | null {
  if (!isRecord(value)) return null;
  if (typeof value.id !== "string" || typeof value.name !== "string") return null;
  if (!Array.isArray(value.layers)) return null;

  const layers = value.layers
    .map(parseLayer)
    .filter((layer): layer is Layer => layer !== null);

  const transitionType =
    typeof value.transitionType === "string" &&
    SCENE_TRANSITIONS.includes(value.transitionType as SceneTransition)
      ? (value.transitionType as SceneTransition)
      : "none";

  return {
    id: value.id,
    name: value.name,
    duration:
      typeof value.duration === "number" ? value.duration : DEFAULT_SCENE_DURATION,
    layers,
    transitionType,
  };
}

export function parseVideoScenes(value: unknown): Scene[] {
  if (!Array.isArray(value)) return [];
  return value.map(parseScene).filter((scene): scene is Scene => scene !== null);
}

export function isVideoSceneDataEmpty(sceneData: Record<string, unknown>): boolean {
  const scenes = parseVideoScenes(sceneData.scenes);
  return scenes.length === 0;
}

/** Omit generated thumbnails — they are re-created in the editor */
export function scenesForPersistence(scenes: Scene[]): Scene[] {
  return scenes.map((scene) => {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars -- strip before save
    const { thumbnailUrl, ...rest } = scene;
    return rest;
  });
}

export interface VideoPersistedSceneData {
  scenes: Scene[];
  activeSceneId: string;
  currentTime?: number;
  pxPerSecond?: number;
  audioFileName?: string | null;
  audioSrc?: string | null;
  audioVolume?: number;
  sceneBackgroundColor?: string;
  sceneAccentColor?: string;
}

export function buildVideoSceneDataPayload(
  input: VideoPersistedSceneData
): Record<string, unknown> {
  return {
    scenes: scenesForPersistence(input.scenes),
    activeSceneId: input.activeSceneId,
    currentTime: input.currentTime,
    pxPerSecond: input.pxPerSecond,
    audioFileName: input.audioFileName,
    audioSrc: input.audioSrc,
    audioVolume: input.audioVolume,
    sceneBackgroundColor: input.sceneBackgroundColor,
    sceneAccentColor: input.sceneAccentColor,
  };
}

export function parseVideoSceneData(
  sceneData: Record<string, unknown>
): VideoPersistedSceneData | null {
  const scenes = parseVideoScenes(sceneData.scenes);
  if (scenes.length === 0) return null;

  const activeSceneId =
    typeof sceneData.activeSceneId === "string" &&
    scenes.some((scene) => scene.id === sceneData.activeSceneId)
      ? sceneData.activeSceneId
      : scenes[0].id;

  return {
    scenes,
    activeSceneId,
    currentTime:
      typeof sceneData.currentTime === "number" ? sceneData.currentTime : 0,
    pxPerSecond:
      typeof sceneData.pxPerSecond === "number" ? sceneData.pxPerSecond : undefined,
    audioFileName:
      typeof sceneData.audioFileName === "string" ? sceneData.audioFileName : null,
    audioSrc: typeof sceneData.audioSrc === "string" ? sceneData.audioSrc : null,
    audioVolume:
      typeof sceneData.audioVolume === "number" ? sceneData.audioVolume : 100,
    sceneBackgroundColor:
      typeof sceneData.sceneBackgroundColor === "string"
        ? sceneData.sceneBackgroundColor
        : DEFAULT_SCENE_BACKGROUND_COLOR,
    sceneAccentColor:
      typeof sceneData.sceneAccentColor === "string"
        ? sceneData.sceneAccentColor
        : DEFAULT_SCENE_ACCENT_COLOR,
  };
}
