import {
  fixOptionalNumber,
  fixOptionalString,
  isArray,
  isBoolean,
  isObject,
  isString,
  isValidFiniteNumber,
  makeFixer,
} from './utils';

export type ClipCreationIntent = {
  id: string;
  possibleClipIds: string[];
  queuedGenerationIds: string[];
  color?: string;
  name: string;
  namePersists: boolean;
  startBeats?: number;
  endBeats?: number;
  startTrimmedBeats: number;
  endTrimmedBeats: number;
};

const fixName = makeFixer(isString, '');
const fixNamePersists = makeFixer(isBoolean, false);
const fixStartTrimmedBeats = makeFixer(isValidFiniteNumber, 0);
const fixEndTrimmedBeats = makeFixer(isValidFiniteNumber, 0);

const fixStringArray = (arr: unknown): string[] => {
  if (!isArray(arr)) {
    return [];
  }
  return arr.filter(isString);
};

export default function fixClipCreationIntent(
  intent: unknown,
  wipeQueuedGenerations: boolean = false
): ClipCreationIntent | null {
  if (!isObject(intent)) {
    return null;
  }

  const c = intent as {
    id: unknown;
    possibleClipIds: unknown;
    queuedGenerationIds: unknown;
    queuedGenerationId?: unknown; // Legacy field
    color: unknown;
    name: unknown;
    namePersists: unknown;
    startBeats: unknown;
    endBeats: unknown;
    startTrimmedBeats: unknown;
    endTrimmedBeats: unknown;
  };

  // Validate that we have an id
  if (!isString(c.id)) {
    return null;
  }

  c.possibleClipIds = fixStringArray(c.possibleClipIds);

  // Migrate old queuedGenerationId to queuedGenerationIds
  if (c.queuedGenerationIds === undefined) {
    c.queuedGenerationIds = [];
    if (isString(c.queuedGenerationId)) {
      (c.queuedGenerationIds as string[]).push(c.queuedGenerationId);
    }
  } else {
    c.queuedGenerationIds = fixStringArray(c.queuedGenerationIds);
  }

  // Clean up legacy field
  if (c.queuedGenerationId !== undefined) {
    delete c.queuedGenerationId;
  }

  // Validate that the intent has either possibleClipIds or queuedGenerationIds
  const hasClipId = (c.possibleClipIds as string[]).length > 0;
  const hasQueuedGeneration = (c.queuedGenerationIds as string[]).length > 0;

  if (
    !hasClipId &&
    (!hasQueuedGeneration || (wipeQueuedGenerations && hasQueuedGeneration))
  ) {
    return null;
  }

  // Clear queued generation IDs in place if we have clipIds
  if (hasClipId) {
    (c.queuedGenerationIds as string[]).length = 0;
  }

  c.color = fixOptionalString(c.color);
  c.name = fixName(c.name);
  c.namePersists = fixNamePersists(c.namePersists);
  c.startBeats = fixOptionalNumber(c.startBeats);
  c.endBeats = fixOptionalNumber(c.endBeats);
  c.startTrimmedBeats = fixStartTrimmedBeats(c.startTrimmedBeats);
  c.endTrimmedBeats = fixEndTrimmedBeats(c.endTrimmedBeats);

  return intent as ClipCreationIntent;
}
