import * as React from 'react';
import {augmentAudioFile} from '@/utils/blob';
import theme from '@/styles/theme';
import {useMediaControls} from '../../hooks/interactive';
import {useFileMetadata, useFileUrl} from '@/categories/blob/react';
import clsx from 'clsx';
import {SpectrogramCanvas, WaveformCanvas} from '@modal-soft/react-wavesurfer';
import {useEnhanced} from '@modal-soft/react-utils';

type AudioMiniFilePreviewDerivedElement = HTMLAudioElement;

export interface AudioMiniFilePreviewProps<F extends Partial<File> = Partial<File>> extends Omit<React.HTMLProps<AudioMiniFilePreviewDerivedElement>, 'controls'> {
  file?: F;
  disabled?: boolean;
  enhanced?: boolean;
}

export const AudioMiniFilePreview = React.forwardRef<AudioMiniFilePreviewDerivedElement, AudioMiniFilePreviewProps>(({
  file,
  style,
  className,
  enhanced: enhancedProp = false,
  disabled = false,
  ...etcProps
}, forwardedRef) => {
  const { fileWithUrl } = useFileUrl({
    file,
  });
  const { fileWithMetadata, error } = useFileMetadata({
    file: fileWithUrl,
    augmentFunction: augmentAudioFile,
  });
  const {
    mediaControllerRef,
    refreshControls,
    reset,
    updateSeekFromPlayback,
    isPlaying,
    isSeeking,
    currentTimeDisplay = 0,
    seekTimeDisplay = 0,
    durationDisplay = 0,
    isSeekTimeCountingDown,
    adjustVolume,
    volumeRef,
    handleAction,
    filenameRef,
    seekRef,
    startSeek,
    endSeek,
    setSeek,
    visualizationId,
    formId,
  } = useMediaControls<HTMLAudioElement>({
    controllerRef: forwardedRef,
    visualizationMode: 'waveform',
  });
  const { enhanced } = useEnhanced({ enhanced: enhancedProp });

  if (!fileWithMetadata) {
    return null;
  }

  const finalSeekTimeDisplay = isSeekTimeCountingDown ? (durationDisplay - seekTimeDisplay) : seekTimeDisplay;
  const finalCurrentTimeDisplay = isSeekTimeCountingDown ? (durationDisplay - currentTimeDisplay) : currentTimeDisplay;

  return (
    <div
      className={clsx(
        'flex flex-col sm:grid sm:grid-cols-3 gap-8 w-full',
        className,
      )}
      style={style}
    >
      <div className="sm:h-full relative col-span-2">
        {
          typeof fileWithMetadata.url === 'string'
          && (
            <div
              className="w-full h-full bg-black flex flex-col items-stretch"
              data-testid="preview"
            >
              <div
                className="w-full flex-auto relative aspect-video sm:aspect-auto"
                key={`${fileWithMetadata?.url ?? ''}:${fileWithMetadata?.type ?? ''}`}
              >
                <audio
                  {...etcProps}
                  controls={!enhanced}
                  ref={mediaControllerRef}
                  onLoadedMetadata={refreshControls}
                  onDurationChange={refreshControls}
                  onEnded={reset}
                  onTimeUpdate={updateSeekFromPlayback}
                >
                  <source
                    key={`${fileWithMetadata?.url ?? ''}:${fileWithMetadata?.type ?? ''}`}
                    src={fileWithMetadata.url}
                    type={fileWithMetadata.type}
                  />
                  Audio playback not supported.
                </audio>
                {enhanced && (
                  <>
                    <div className="flex justify-end w-full h-full gap-4 absolute top-0 right-0 z-[5] px-4">
                      <div className="contents">
                        <input
                          type="radio"
                          name="visualizationMode"
                          value="waveform"
                          className="sr-only peer/waveform"
                          defaultChecked
                          id={`${visualizationId}-waveform`}
                        />
                        <label
                          htmlFor={`${visualizationId}-waveform`}
                          className={clsx(
                            'relative z-[5]',
                            'h-12 flex items-center justify-center leading-none gap-4 select-none',
                            'text-primary cursor-pointer',
                            'peer-focus/waveform:text-secondary',
                            'peer-active/waveform:text-tertiary',
                            'peer-checked/waveform:text-tertiary',
                            'peer-disabled/waveform:text-primary peer-disabled/waveform:cursor-not-allowed peer-disabled/waveform:opacity-50',
                          )}
                        >
                          <span
                            className={clsx(
                              'flex items-center uppercase font-bold h-full w-full whitespace-nowrap overflow-hidden text-ellipsis',
                            )}
                          >
                            Waveform
                          </span>
                        </label>
                        <WaveformCanvas
                          className={clsx(
                            'absolute w-full sm:h-full top-0 left-0 block object-center object-contain flex-auto aspect-video sm:aspect-auto bg-primary/10 cursor-text opacity-0',
                            'peer-checked/waveform:opacity-100',
                          )}
                          audioRef={mediaControllerRef}
                          data-testid="preview"
                          barWidth={1}
                          barGap={1}
                          progressColor={`rgb(${theme['color-primary']})`}
                          waveColor={`rgb(${theme['color-primary'].split(' ').map((c) => Math.floor(Number(c) / 2)).join(' ')})`}
                          interact
                          // waveColor={`rgb(${theme.primary})`}
                          // barHeight={4}
                          // minPxPerSec={20000}
                          // hideScrollbar
                          // autoCenter
                          // autoScroll
                        />
                      </div>
                      <div
                        className="contents"
                      >
                        <input
                          type="radio"
                          name="visualizationMode"
                          value="spectrum"
                          className="sr-only peer/waveform"
                          id={`${visualizationId}-spectrum`}
                        />
                        <label
                          htmlFor={`${visualizationId}-spectrum`}
                          className={clsx(
                            'relative z-[5]',
                            'h-12 flex items-center justify-center leading-none gap-4 select-none',
                            'text-primary cursor-pointer',
                            'peer-focus/waveform:text-secondary',
                            'peer-active/waveform:text-tertiary',
                            'peer-checked/waveform:text-tertiary',
                            'peer-disabled/waveform:text-primary peer-disabled/waveform:cursor-not-allowed peer-disabled/waveform:opacity-50',
                          )}
                        >
                          <span
                            className={clsx(
                              'flex items-center uppercase font-bold h-full w-full whitespace-nowrap overflow-hidden text-ellipsis',
                            )}
                          >
                            Spectrum
                          </span>
                        </label>
                        <SpectrogramCanvas
                          className={clsx(
                            'absolute w-full sm:h-full top-0 left-0 block object-center object-contain flex-auto aspect-video sm:aspect-auto bg-primary/10 pointer-events-none opacity-0',
                            'peer-checked/waveform:opacity-100',
                          )}
                          audioRef={mediaControllerRef}
                          data-testid="preview"
                          barWidth={1}
                          barGap={1}
                          waveColor={`rgb(${theme['color-primary']})`}
                          cursorWidth={2}
                          minPxPerSec={20000}
                          hideScrollbar
                          autoCenter
                          autoScroll
                        />
                      </div>
                    </div>
                  </>
                )}
              </div>
            </div>
          )
        }
      </div>
    </div>
  );
});

AudioMiniFilePreview.displayName = 'AudioMiniFilePreview';
