/* eslint jsx-a11y/no-static-element-interactions: warn */
import clsx from 'clsx';
import { observer } from 'mobx-react-lite';
import { RefObject, useCallback, useEffect, useRef, useState } from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import CloseButton from '@/components/button/CloseButton';
import ImageWithFallback from '@/components/image/ImageWithFallback';
import D3Waveform from '@/components/playbar/D3Waveform';
import { PauseIcon, PlayIcon } from '@/icons';
import { Clip } from '@/state/clipStore';
import { PlanFeature } from '@/state/sessionStore';
import { getClipTitle } from '@/utils/clip';
import { isFeatureEnabledForPlan } from '@/utils/session';
import { decodeTimeFormat, encodeTimeFormat } from '@/utils/utils';

import { AnimatedTabs } from './AnimatedTabs';
import { getPromptMaxLengthForModel } from './utils';

type Props = {
  clip?: Clip;
  ref?: RefObject<any>;
  index?: number;
  coverExtendMode: 'cover' | 'extend';
};

export const AudioSection = observer(
  ({ clip, ref, index, coverExtendMode }: Props) => {
    const { clips, genForm, createV2, playbar, session } = useStores();
    const continueClipContainerRef = useRef<any>(null);
    const [width, setWidth] = useState<number | null>(null);

    const updateContinueAt = useCallback(
      (continueAt: number) => {
        if (
          clip &&
          genForm.continueClipDuration &&
          continueAt > 1 &&
          continueAt <= genForm.continueClipDuration
        ) {
          genForm.setContinueAtSeconds(continueAt);
          createV2.setActiveContinueAtSeconds(encodeTimeFormat(continueAt));
        }
      },
      [clip, createV2, genForm]
    );

    useEffect(() => {
      if (!continueClipContainerRef.current) return;
      const resizeObserver = new ResizeObserver(() => {
        setWidth(
          continueClipContainerRef.current.getBoundingClientRect().width
        );
      });
      resizeObserver.observe(continueClipContainerRef.current);
      return () => {
        resizeObserver.disconnect();
      };
    }, [continueClipContainerRef]);

    if (!clip) {
      return null;
    }
    return (
      <div className='flex flex-1 flex-col' ref={ref}>
        {/* <div className='text-lg mx-4 my-2'>Audio</div> */}
        <div className='h-auto min-h-[160px] w-auto rounded-[30px] bg-background-secondary p-4'>
          <div className='flex w-full flex-col gap-4'>
            <div className='flex flex-row items-center gap-2'>
              <span className='ml-4 line-clamp-1 flex-1 text-xl'>
                {getClipTitle(clip)}
              </span>
              <input
                className={clsx(
                  'h-8 w-20 rounded-full border border-white/10 bg-transparent pl-2 outline-none',
                  {
                    'brightness-50': coverExtendMode === 'cover',
                  }
                )}
                value={
                  coverExtendMode === 'cover'
                    ? ''
                    : createV2.activeContinueAtSeconds !== null &&
                        createV2.activeContinueAtSeconds !== ''
                      ? createV2.activeContinueAtSeconds
                      : encodeTimeFormat(genForm.continueClipDuration) || ''
                }
                type='text'
                disabled={coverExtendMode === 'cover'}
                onKeyDown={(e) => {
                  if (e.key === 'Enter') {
                    const decodedTime = decodeTimeFormat(
                      createV2.activeContinueAtSeconds || ''
                    );
                    if (
                      decodedTime !== null &&
                      decodedTime > 0 &&
                      decodedTime <= (genForm.continueClipDuration || 0)
                    ) {
                      genForm.setContinueAtSeconds(decodedTime);
                    } else {
                      createV2.setActiveContinueAtSeconds(
                        encodeTimeFormat(genForm.continueClipDuration)
                      );
                    }
                  }
                }}
                onBlur={() => {
                  const decodedTime = decodeTimeFormat(
                    createV2.activeContinueAtSeconds || ''
                  );
                  if (
                    decodedTime !== null &&
                    decodedTime > 0 &&
                    decodedTime <= (genForm.continueClipDuration || 0)
                  ) {
                    updateContinueAt(decodedTime);
                  } else {
                    createV2.setActiveContinueAtSeconds(
                      encodeTimeFormat(genForm.continueClipDuration)
                    );
                  }
                }}
                onChange={(e) => {
                  createV2.setActiveContinueAtSeconds(e.target.value);
                }}
              ></input>
              <CloseButton
                className='bg-transparent backdrop-blur-none'
                onClick={() => {
                  if (createV2.coverExtendMode === 'cover_extend') {
                    if (coverExtendMode === 'extend') {
                      createV2.setCoverExtendMode('cover');
                      genForm.resetContinueClip();
                    } else {
                      createV2.setCoverExtendMode('extend');
                      genForm.resetCoverClip();
                    }
                  } else {
                    genForm.resetContinueClip();
                    genForm.resetCoverClip();
                    genForm.setIsRemixCreate(false);
                  }
                  if (
                    coverExtendMode === 'cover' &&
                    createV2.activeTitle.endsWith(' (Cover)')
                  ) {
                    createV2.setActiveTitle(
                      createV2.activeTitle.replace(' (Cover)', '')
                    );
                  }
                }}
              />
            </div>
            <div className='flex flex-row items-center'>
              <div className='relative h-[80px] w-[80px]'>
                <ImageWithFallback
                  src={clip?.image_url}
                  width={80}
                  className='absolute top-0 left-0 h-full rounded-lg brightness-50'
                  alt={`Image for ${getClipTitle(clip)}`}
                />
                <Button
                  className='absolute top-0 left-0 h-[80px] w-[80px] border-0 before:border-0'
                  shape={ButtonShape.Pill}
                  size={ButtonSize.Large}
                  iconClassName='w-8 h-8'
                  icon={
                    playbar.clip?.id === clip?.id && playbar.isPlaying
                      ? PauseIcon
                      : PlayIcon
                  }
                  variant={ButtonVariant.Secondary}
                  onClick={() => {
                    if (playbar.clip?.id === clip?.id) {
                      playbar.togglePlay();
                    } else {
                      playbar.playClip(clip);
                    }
                  }}
                />
              </div>
              <div
                className='relative ml-4 h-20 flex-1 overflow-hidden rounded-xl border border-white/5 bg-white/5 py-2'
                ref={continueClipContainerRef}
              >
                {!!clip ? (
                  <>
                    <D3Waveform
                      index={index}
                      height={64}
                      fillColor={'rgba(255,255,255,0.6)'}
                      strokeColor={'rgba(0,0,0,0.1)'}
                      className='py-0'
                      clip={clip}
                      setWaveformStartInput={() => {}}
                      setWaveformEndInput={() => {}}
                      startPosition={parseInt(
                        createV2.activeContinueAtSeconds || '0'
                      )}
                      endPosition={null}
                      setStartPosition={(position: number | null) => {
                        if (position === null) {
                          return;
                        }
                        createV2.setActiveContinueAtSeconds(
                          position?.toString() || null
                        );
                      }}
                      setEndPosition={() => {}}
                    />
                  </>
                ) : null}
                {!!clips.pregenWaveformByClipId[clip.id] ? (
                  <>
                    <div
                      onMouseDown={(e) => {
                        e.stopPropagation();
                        if (!continueClipContainerRef.current) {
                          return;
                        }
                        if (coverExtendMode === 'extend') {
                          createV2.setIsDraggingContinueAtSeconds(true);
                          createV2.setDraggingContinueAtSecondsStartPosition(
                            e.clientX
                          );
                        }
                      }}
                      onMouseUp={(e) => {
                        if (
                          !createV2.hasDraggedContinueAtSeconds ||
                          coverExtendMode === 'cover'
                        ) {
                          const percent =
                            (e.clientX -
                              continueClipContainerRef.current.getBoundingClientRect()
                                .left) /
                            (width ||
                              continueClipContainerRef.current.getBoundingClientRect()
                                .width);
                          if (playbar.clip?.id === clip?.id) {
                            playbar.userSetCurrentProgress(percent * 100);
                          } else {
                            playbar.playClip(
                              clip,
                              undefined,
                              undefined,
                              false,
                              (clip?.metadata?.duration || 0) * percent
                            );
                          }
                        }
                        createV2.setIsDraggingContinueAtSeconds(false);
                        createV2.setHasDraggedContinueAtSeconds(false);
                        createV2.setDraggingContinueAtSecondsStartPosition(
                          null
                        );
                        e.stopPropagation();
                      }}
                      onMouseLeave={() => {
                        createV2.setIsDraggingContinueAtSeconds(false);
                      }}
                      onMouseMove={(e) => {
                        e.stopPropagation();
                        if (!continueClipContainerRef.current) {
                          return;
                        }
                        if (
                          createV2.isDraggingContinueAtSeconds &&
                          (Math.abs(
                            e.clientX -
                              (createV2.draggingContinueAtSecondsStartPosition ||
                                0)
                          ) > 10 ||
                            createV2.hasDraggedContinueAtSeconds)
                        ) {
                          createV2.setHasDraggedContinueAtSeconds(true);
                          const percent =
                            (e.clientX -
                              continueClipContainerRef.current.getBoundingClientRect()
                                .left) /
                            (width ||
                              continueClipContainerRef.current.getBoundingClientRect()
                                .width);
                          const continueTimeSecs =
                            (clip?.metadata?.duration || 0) * percent;
                          updateContinueAt(continueTimeSecs);
                        }
                      }}
                      className={clsx(
                        'absolute top-0 left-0 z-80 h-full w-full cursor-e-resize border-primary'
                      )}
                    />
                    <div
                      className={clsx(
                        'pointer-events-none absolute top-0 left-0 z-100 h-full rounded-lg border-2 border-r-12 border-l-4 border-primary bg-clip-border backdrop-contrast-20',
                        {
                          hidden: coverExtendMode === 'cover',
                        }
                      )}
                      onMouseUp={(e) => {
                        createV2.setIsDraggingContinueAtSeconds(false);
                        createV2.setHasDraggedContinueAtSeconds(false);
                        if (!createV2.hasDraggedContinueAtSeconds) {
                          return;
                        }
                        e.stopPropagation();
                      }}
                      onMouseDown={(e) => {
                        e.stopPropagation();
                        if (!continueClipContainerRef.current) {
                          return;
                        }
                        createV2.setIsDraggingContinueAtSeconds(true);
                        const percent =
                          (e.clientX -
                            continueClipContainerRef.current.getBoundingClientRect()
                              .left) /
                          (width ||
                            continueClipContainerRef.current.getBoundingClientRect()
                              .width);
                        updateContinueAt(
                          (clip?.metadata?.duration || 0) * percent
                        );
                      }}
                      onMouseMove={(e) => {
                        e.stopPropagation();
                        if (!continueClipContainerRef.current) {
                          return;
                        }
                        if (createV2.isDraggingContinueAtSeconds) {
                          createV2.setHasDraggedContinueAtSeconds(true);
                          const percent =
                            (e.clientX -
                              continueClipContainerRef.current.getBoundingClientRect()
                                .left) /
                            (width ||
                              continueClipContainerRef.current.getBoundingClientRect()
                                .width);
                          const newContinueAt =
                            (clip?.metadata?.duration || 0) * percent;
                          updateContinueAt(newContinueAt);
                        }
                      }}
                      style={{
                        width:
                          (clip?.metadata?.duration || 0) > 0 &&
                          !!continueClipContainerRef.current
                            ? `${((genForm.continueAtSeconds || 0) / (clip?.metadata?.duration || 0)) * (width || continueClipContainerRef.current.getBoundingClientRect().width)}px`
                            : '0px',
                      }}
                    >
                      <div className='absolute top-[30px] right-[-21px]'>
                        <PlayIcon className='h-3 w-3' />
                      </div>
                      <div className='absolute top-[28px] right-0 z-120 -mr-[8px] h-4 w-1 rounded-md bg-dumbo-450' />
                    </div>
                    <div
                      className={clsx(
                        'pointer-events-none absolute top-0 right-0 h-full bg-[rgba(56,52,53,0.6)]',
                        {
                          hidden: coverExtendMode === 'cover',
                        }
                      )}
                      style={{
                        width:
                          (clip?.metadata?.duration || 0) > 0 &&
                          !!continueClipContainerRef.current
                            ? `${(1.0 - (genForm.continueAtSeconds || 0) / (clip?.metadata?.duration || 0)) * (width || continueClipContainerRef.current.getBoundingClientRect().width)}px`
                            : '0px',
                      }}
                    ></div>
                  </>
                ) : null}
              </div>
            </div>

            {createV2.coverExtendMode === 'cover_extend' ? (
              <span className='font-extrabold'>
                {coverExtendMode === 'extend' ? 'Extend' : 'Cover'}
              </span>
            ) : (
              <AnimatedTabs
                id={`audio-tabs-${index || '1'}`}
                onChange={(option) => {
                  createV2.setCoverExtendMode(
                    option.value as 'cover' | 'extend'
                  );
                  if (option.value === 'cover') {
                    genForm.resetContinueClip();
                    genForm.setCoverClip(clip);
                    const lyricsMaxLength = getPromptMaxLengthForModel(
                      genForm.mv
                    );
                    createV2.setActiveLyrics(
                      (clip.metadata?.prompt || '').slice(0, lyricsMaxLength)
                    );
                    createV2.setActiveLyricsMode('custom');
                    createV2.setActiveLyricsModeTab('custom');
                    createV2.setActiveTitle(`${getClipTitle(clip)} (Cover)`);
                  } else if (option.value === 'extend') {
                    genForm.resetCoverClip();
                    genForm.setContinueClip(clip);
                    if (
                      createV2.activeTitle === '' ||
                      createV2.activeTitle.endsWith(' (Cover)')
                    ) {
                      createV2.setActiveTitle(getClipTitle(clip) || '');
                    }
                  }
                }}
                value={createV2.coverExtendMode || undefined}
                options={[
                  { value: 'extend', title: 'Extend' },
                  {
                    value: 'cover',
                    title: 'Cover',
                    disabled:
                      !isFeatureEnabledForPlan(session, PlanFeature.Cover) &&
                      !session.flags?.['remix'],
                  },
                ]}
              />
            )}
          </div>
        </div>
      </div>
    );
  }
);
