import { observer } from 'mobx-react-lite';
import {
  RefObject,
  useCallback,
  useContext,
  useEffect,
  useRef,
  useState,
} from 'react';
import {
  Dialog,
  DialogTrigger,
  OverlayArrow,
  Popover,
} from 'react-aria-components';

import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import audioContext from '@/lib/audioContext';
import { AUDIO_FILE_TYPES_STRING, MENUS_Z_INDEX } from '@/utils/constants';
import removeFileExtension from '@/utils/removeFileExtension';

import UploadStateContext from '../uploaderV2/UploadStateContext';

export const AudioDropdown = observer(
  ({
    renderTriggerButton,
  }: {
    renderTriggerButton: (
      callback: () => void,
      triggerRef: RefObject<any>
    ) => React.ReactElement;
  }) => {
    const { setUploadFileConfig, setIsRecordingMode, setIsUploadInProgress } =
      useContext(UploadStateContext);
    const fileInputRef = useRef<any>(null);
    const popoverRef = useRef<any>(null);
    const handleFileSelect = useCallback(
      async (e: { target: { files: File[] | FileList | null } }) => {
        const files = Array.from(e.target.files || []);
        if (files.length === 0) {
          setUploadFileConfig(null);
          return;
        }
        const file = files[0];
        const arrayBuffer = await file.arrayBuffer();
        const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
        setUploadFileConfig({
          clientSelectedFile: file,
          audioBuffer: audioBuffer,
          title: removeFileExtension(file.name),
        });
        if (fileInputRef.current) fileInputRef.current.value = '';
        setIsUploadInProgress(true);
        setIsRecordingMode(false);
      },
      []
    );
    const [isAudioDropdownOpen, setIsAudioDropdownOpen] = useState(false);
    const audioButtonRef = useRef<any>(null);

    const handleClickAudio = useCallback(() => {
      setIsAudioDropdownOpen(!isAudioDropdownOpen);
    }, [isAudioDropdownOpen]);

    const handleOnOpenChange = useCallback(
      (isOpen: boolean) => {
        setIsAudioDropdownOpen(isOpen);
      },
      [isAudioDropdownOpen]
    );

    useEffect(() => {
      if (!isAudioDropdownOpen) return;

      const handleClickOutside = (event: MouseEvent) => {
        if (
          popoverRef.current &&
          !popoverRef.current.contains(event.target) &&
          audioButtonRef.current &&
          !audioButtonRef.current.contains(event.target)
        ) {
          setIsAudioDropdownOpen(false);
        }
      };

      document.addEventListener('mousedown', handleClickOutside);

      return () => {
        document.removeEventListener('mousedown', handleClickOutside);
      };
    }, [isAudioDropdownOpen]);

    return (
      <>
        {renderTriggerButton(handleClickAudio, audioButtonRef)}
        <input
          type='file'
          ref={fileInputRef}
          onChange={handleFileSelect}
          accept={AUDIO_FILE_TYPES_STRING}
          className='hidden'
        />
        <DialogTrigger>
          <Popover
            ref={popoverRef}
            isNonModal
            triggerRef={audioButtonRef}
            placement='top'
            className='rounded-[30px] outline-none focus:outline-none'
            style={{
              boxShadow: '0px 0px 8px rgba(0,0,0,0.4)',
              zIndex: MENUS_Z_INDEX,
            }}
            isOpen={isAudioDropdownOpen}
            onOpenChange={handleOnOpenChange}
            shouldCloseOnInteractOutside={(el) => {
              return (
                el !== audioButtonRef.current &&
                !audioButtonRef.current.contains(el)
              );
            }}
          >
            <OverlayArrow></OverlayArrow>
            <Dialog className='outline-none'>
              <div className='relative flex flex-col gap-px overflow-hidden rounded-[20px] border-[0.5px] border-border-primary-glass bg-background-secondary'>
                <div className='absolute top-0 right-0 bottom-0 left-0 bg-background-fog-thick' />
                <Button
                  variant={ButtonVariant.Standard}
                  shape={ButtonShape.Rectangle}
                  onClick={() => {
                    setIsAudioDropdownOpen(false);
                    fileInputRef.current?.click();
                  }}
                  size={ButtonSize.Large}
                  className='border-0'
                >
                  Upload
                </Button>
                <Button
                  variant={ButtonVariant.Standard}
                  shape={ButtonShape.Rectangle}
                  onClick={() => {
                    setIsUploadInProgress(true);
                    setIsAudioDropdownOpen(false);
                    setIsRecordingMode(true);
                  }}
                  size={ButtonSize.Large}
                  className='border-0'
                >
                  Record
                </Button>
              </div>
            </Dialog>
          </Popover>
        </DialogTrigger>
      </>
    );
  }
);
