import { getBeatsFromZero } from '@suno/studiokit/timeMapping';
import { useCallback, useRef } from 'react';

import { toast } from '@/components/toast/Toast';
import { useContextSelector } from '@/hooks/useContextSelector';

import StudioContext from './StudioContext';
import { getDerivedTiming } from './selectors';

export default function UploadButtonRenderer({
  renderButton,
}: {
  renderButton: (handleUpload: () => void) => React.ReactNode;
}) {
  const stateRef = useContextSelector(StudioContext, (ctx) => ctx.stateRef);
  const uploadInputRef = useRef<HTMLInputElement>(null);
  const handleUpload = useCallback(() => {
    uploadInputRef.current?.click();
  }, []);

  const arrangeFile = useContextSelector(
    StudioContext,
    (ctx) => ctx.arrangeFile
  );

  const handleReceiveFile = useCallback(
    async (e: React.ChangeEvent<HTMLInputElement>) => {
      const file = e.target.files?.[0];
      if (file) {
        try {
          const arrayBuffer = await file.arrayBuffer();
          const audioContext = new (window.AudioContext ||
            (window as any).webkitAudioContext)();
          const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
          const timing = getDerivedTiming(stateRef.current);

          arrangeFile(
            null,
            {
              startBeats: 0,
              endBeats: getBeatsFromZero(audioBuffer.duration, timing),
            },
            file,
            audioBuffer
          );
        } catch (error) {
          toast({
            title: 'Error',
            description: 'Failed to upload file',
            status: 'error',
          });
        }
      }
    },
    [arrangeFile, stateRef]
  );

  return (
    <>
      <input
        ref={uploadInputRef}
        type='file'
        onChange={handleReceiveFile}
        className='fixed -z-1000 hidden'
      />
      {renderButton(handleUpload)}
    </>
  );
}
