import { getWarpBeatsFromSeconds } from '@suno/studiokit/warpUtils';
import { useEffect } from 'react';

import updateClips from './actions/updateClips';
import { useClips } from './hooks/useClips';
import { getStreamingClipIds, getStudioClipsByClipId } from './selectors';
import { StudioProjectState } from './types';
import { getMaximumKnownClipDuration } from './useFfmpegBufferCache';

export default function useStreamingClipResolver(
  state: StudioProjectState,
  rewriteHistory: (
    transformState: (state: StudioProjectState) => StudioProjectState
  ) => void
) {
  const streamingClipIds = getStreamingClipIds(state);
  const { clips } = useClips(streamingClipIds);

  useEffect(() => {
    const completeClips = Object.values(clips).filter((clip) => {
      return clip.status === 'complete' && clip.metadata.duration;
    });
    if (completeClips.length > 0) {
      rewriteHistory((state) => {
        const studioClipsByClipId = getStudioClipsByClipId(state);
        const clipsToUpdate = completeClips.flatMap(
          (clip) => studioClipsByClipId[clip.id] ?? []
        );
        return updateClips(
          clipsToUpdate.map((c) => c.id),
          (c) => {
            const duration = getMaximumKnownClipDuration(clips[c.clipId!]);
            if (!duration) {
              console.warn(
                'completed streaming clip',
                c.id,
                'has no duration. ',
                `(duration = ${duration})`
              );
              return { ...c, streaming: false };
            } else {
              let endBeats = c.endBeats;
              let loopEndBeats = c.loop.endBeats;
              if (!c.warp.awaitingAnalysis) {
                const readEndBeats = getWarpBeatsFromSeconds(c.warp, duration);
                endBeats = Math.min(
                  c.endBeats,
                  c.startBeats + (readEndBeats - c.readStartBeats)
                );
                loopEndBeats = Math.min(c.loop.endBeats, readEndBeats);
              }

              return {
                ...c,
                streaming: false,
                endBeats,
                loop: {
                  ...c.loop,
                  endBeats: loopEndBeats,
                },
              };
            }
          }
        )(state);
      });
    }
  }, [clips]);
}
