import { Clip } from '@/state/clipStore';
import { EMPTY_UUID } from '@/utils/constants';

import {
  CustomPrompt,
  GenerateParams,
  PromptType,
  ReferenceType,
  getClipModelTier,
} from './useGenerate';

const getClipGeneratePayload = (clip: Clip): GenerateParams => {
  // Don't allow regenerating from a private clip not owned by the user (zeroed-out UUID)
  if (
    clip.metadata.edited_clip_id === EMPTY_UUID ||
    clip.metadata.cover_clip_id === EMPTY_UUID ||
    clip.metadata.artist_clip_id === EMPTY_UUID
  ) {
    throw new Error(
      'Cannot regenerate from a private clip not shared with you'
    );
  }

  const result: GenerateParams = {
    modelTier: getClipModelTier(clip, true),
    modelOverride: clip.model_name ?? undefined,
    disableVolumeNormalization: clip.metadata.normalize_volume === false,
    prompt: {
      type: PromptType.Custom,
      title: clip.title,
      lyrics: clip.metadata.prompt || undefined,
      tags: clip.metadata.tags || undefined,
      negativeTags: clip.metadata.negative_tags || undefined,
    },
  };

  if (clip.metadata.infill || clip.metadata.task === 'stem_condition_infill') {
    const historyEntry = clip.metadata.history?.slice(-1)[0] as any;
    if (historyEntry) {
      (result.prompt as CustomPrompt).lyrics =
        (clip as any).metadata.continued_aligned_prompt || '';
      const futureContextLength =
        historyEntry.infill_context_end_s - historyEntry.infill_end_s;

      const pastContextLength =
        historyEntry.infill_start_s - historyEntry.infill_context_start_s;

      result.references = [
        {
          type:
            clip.metadata.task === 'fixed_infill'
              ? ReferenceType.FixedInfill
              : ReferenceType.Infill,
          clipId: clip.metadata.edited_clip_id!,
          startSeconds: historyEntry.infill_start_s,
          endSeconds: historyEntry.infill_end_s,
          contextStartSeconds: historyEntry.infill_context_start_s,
          contextEndSeconds: historyEntry.infill_context_end_s,
          durationSeconds: historyEntry.infill_dur_s,
          contextLyrics: clip.metadata.prompt || '',
          infillLyrics: historyEntry.infill_lyrics,
          lyricsUpdated: (clip as any).metadata.lyrics_updated ?? false,
        },
      ];

      if (result.references[0].type === ReferenceType.Infill) {
        result.references[0].generateFullContext =
          Math.abs(historyEntry.include_future_s - futureContextLength) <
            0.02 &&
          Math.abs(historyEntry.include_history_s - pastContextLength) < 0.02;
      }
    }
    if (clip.metadata.task === 'stem_condition_infill') {
      result.references?.push({
        type: ReferenceType.StemCondition,
        clipId: clip.metadata.stem_from_id!,
        stemControlTags: clip.metadata.control_tags!,
        startSeconds: historyEntry.infill_start_s,
        endSeconds: historyEntry.infill_end_s,
      });
    }
  } else if (
    clip.metadata.task === 'extend' ||
    clip.metadata.task === 'upload_extend'
  ) {
    const historyEntry = clip.metadata.history?.slice(-1)[0] as any;
    if (historyEntry) {
      result.references = [
        {
          type: ReferenceType.Extend,
          clipId: clip.metadata.edited_clip_id!,
          startSeconds: historyEntry.continue_at,
          isUpload: clip.metadata.task === 'upload_extend',
          contextLyrics: (clip as any).metadata.continued_aligned_prompt || '',
          lyricsUpdated: (clip as any).metadata.lyrics_updated ?? false,
        },
      ];
    }
  } else if (clip.metadata.task === 'cover') {
    result.references = [
      {
        type: ReferenceType.Cover,
        clipId: clip.metadata.cover_clip_id!,
        startSeconds: clip.metadata.cover_start_s ?? undefined,
        endSeconds: clip.metadata.cover_end_s ?? undefined,
      },
    ];
  } else if (
    clip.metadata.task === 'artist_consistency' &&
    clip.metadata.persona_id
  ) {
    result.references = [
      {
        type: ReferenceType.Persona,
        clipId: clip.metadata.artist_clip_id!,
        personaId: clip.metadata.persona_id,
        startSeconds: (clip.metadata as any).artist_start_s ?? undefined,
        endSeconds: (clip.metadata as any).artist_end_s ?? undefined,
      },
    ];
  } else if (clip.metadata.task === 'gen_stem') {
    result.references = [
      {
        type: ReferenceType.GenStem,
        clipId: clip.metadata.edited_clip_id!,
        stemType: clip.metadata.stem_type_id ?? undefined,
        stemTypeGroup: clip.metadata.stem_type_group_name ?? undefined,
        stemTask: clip.metadata.stem_task ?? undefined,
      },
    ];
  } else if (clip.metadata.task === 'stem_condition') {
    result.references = [
      {
        type: ReferenceType.StemCondition,
        clipId: clip.metadata.stem_from_id!,
        stemControlTags: clip.metadata.control_tags!,
      },
    ];
  } else if (clip.metadata.task === 'cover_infill') {
    throw new Error('Infill cover is not supported');
  } else if (clip.metadata.task === 'artist_infill') {
    throw new Error('Artist infill is not supported');
  }

  return result;
};

export default getClipGeneratePayload;
