import {AudioTrack} from '@modules/chats/instances/TrackPlayer';
import {
  ExtendedMessage,
  ExtendedMessageType,
} from '@modules/chats/interfaces/models/extendedMessage';
import {
  FileDownloadStatus,
  useAttachments,
} from '@modules/chats/store/zustand/useAttachments';
import {useAudioTrackPlayer} from '@modules/chats/contexts/AudioPlayerContext';
import {MediaType} from '@modules/chats/interfaces';
import {useEvent} from '@shared/hooks/useEvent';
import {asyncMap, wait} from '@shared/utils';

const getAudioFile = (msg: ExtendedMessage) => {
  if (msg.extendedType === ExtendedMessageType.Default) {
    const attachment = msg.data.attachments?.[0];
    const pendingAsset = msg.data.pendingAssets?.[0];
    if (attachment && attachment.metadata.format === 'audio') {
      return attachment;
    } else if (pendingAsset && pendingAsset.type === MediaType.AUDIO) {
      return pendingAsset;
    }
  }
  return null;
};

export const usePreparePlaylist = (extendedMessages: ExtendedMessage[]) => {
  const {initializePlaylist} = useAudioTrackPlayer();

  return useEvent(async (index: number, onReady?: () => void) => {
    const tracks: AudioTrack[] = [];

    const audioMessagesData = [];
    for (let i = index; i < extendedMessages.length; i++) {
      const msg = extendedMessages[i];

      const file = getAudioFile(msg);

      if (file?.id) {
        const assetItem = useAttachments
          .getState()
          .downloadsByMessage.get(msg.id)?.[file.id];

        if (!assetItem) {
          continue;
        }

        audioMessagesData.push({
          id: msg.id,
          assetItem,
        });
      } else {
        break;
      }
    }

    await asyncMap(audioMessagesData, async ({id, assetItem}) => {
      const tryToAdd = async (attempt = 1): Promise<void> => {
        if (attempt > 5) {
          return;
        }

        if (assetItem?.state === FileDownloadStatus.DONE) {
          tracks.push({
            id,
            uri: assetItem.uri || assetItem.remoteUrl,
          });
        } else {
          await wait(500);
          return await tryToAdd(attempt + 1);
        }
      };
      await tryToAdd();
    });

    if (tracks.length) {
      initializePlaylist(tracks);
      onReady?.();
    }
  });
};
