'use client';

import '@uppy/audio/dist/style.min.css';
import '@uppy/core/dist/style.min.css';
import '@uppy/dashboard/dist/style.min.css';
import { Dashboard } from '@uppy/react';
import { observer } from 'mobx-react-lite';
import { useEffect, useMemo, useState } from 'react';
import storageAvailable from 'storage-available';

import { useStores } from '@/app/(root)/AppProviders';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import AddImageModalContent from '@/components/modal/editClipMetadata/AddImageModalContent';
import { EditClipMetadataForm } from '@/components/modal/editClipMetadata/EditClipMetadataForm';
import SpinnerSVG from '@/components/svg/SpinnerSVG';
import useEditClipMetadata from '@/hooks/useEditClipMetadata';
import { AudioFileIcon, CloseIcon } from '@/icons';
import { useApiClient } from '@/lib/apiClient';
import {
  TransactionLogger,
  createTransactionLogger,
} from '@/logging/logWebUserEvent';
import { AUDIO_UPLOAD_TOS_STORAGE_KEY } from '@/utils/constants';

import { UploadState } from './VideoUploadState';
import './style.css';

const UploadWrapper = ({
  onFinish,
  onClose,
  setShouldConfirmClose,
  isConfirmingClose,
  setIsConfirmingClose,
}: {
  onFinish: (
    uploadId: string | null,
    title: string,
    imageUrl: string,
    uploadType: string | null,
    s3id: string | null,
    transactionLogger: TransactionLogger
  ) => void;
  onClose?: () => void;
  setShouldConfirmClose?: (value: boolean) => void;
  isConfirmingClose?: boolean;
  setIsConfirmingClose?: (value: boolean) => void;
}) => {
  const apiClient = useApiClient();

  const uploadState = useMemo(
    () => new UploadState(apiClient, { setShouldConfirmClose }),
    [apiClient, setShouldConfirmClose]
  );

  return (
    <VideoUploader
      state={uploadState}
      onFinish={onFinish}
      onClose={onClose}
      isConfirmingClose={isConfirmingClose}
      setIsConfirmingClose={setIsConfirmingClose}
    />
  );
};

const VideoUploader = observer(
  ({
    state,
    onFinish,
    onClose,
    isConfirmingClose,
    setIsConfirmingClose,
  }: {
    state: UploadState;
    onFinish: (
      uploadId: string | null,
      title: string,
      imageUrl: string,
      uploadType: string | null,
      s3Id: string | null,
      transactionLogger: TransactionLogger
    ) => void;
    onClose?: () => void;
    isConfirmingClose?: boolean;
    setIsConfirmingClose?: (value: boolean) => void;
  }) => {
    const {
      editedTitle,
      setEditedTitle,
      editedImagePrompt,
      setEditedImagePrompt,
      currentImage,
      setCurrentImage,
      isGenerating,
      setIsGenerating,
      addedImages,
      setAddedImages,
      isAddingImage,
      setIsAddingImage,
      addingImageDataURL,
      setAddingImageDataURL,
      addingImageChanged,
      setAddingImageChanged,
      continuedClips,
      initialImageURL,
      setInitialImageURL,
      isLoading,
      setIsLoading,
      currentLyrics,
      setCurrentLyrics,
      setS3Id,
      //currentActiveClip,
      //setCurrentActiveClip,
      //setContinuedClips,
    } = useEditClipMetadata();

    const { library } = useStores();
    const clipId = library.activeClip?.id || '';

    const [isConfirmingTOS, setIsConfirmingTOS] = useState(false);

    useEffect(() => {
      if (state.uploadClipMetadata) {
        //setCurrentActiveClip(state.uploadClip);
        setEditedTitle(state.uploadClipMetadata?.title || '');
        setCurrentImage(state.uploadClipMetadata?.imageUrl);
      }
    }, [state.uploadClipMetadata]);

    const truncateFilename = (filename: string) => {
      const TRUNCATE_LENGTH = 20;
      const segments = filename.split('.');
      if (filename.length < TRUNCATE_LENGTH) {
        return filename;
      }
      if (segments.length === 1) {
        return `${filename.slice(0, TRUNCATE_LENGTH)}${
          filename.length > TRUNCATE_LENGTH ? '...' : ''
        }`;
      }
      const ext = segments[segments.length - 1];
      const name = segments.slice(0, segments.length - 1).join('');
      return `${name.slice(0, TRUNCATE_LENGTH / 2)}${
        name.length > TRUNCATE_LENGTH ? '...' : ''
      }${name.slice(name.length - TRUNCATE_LENGTH / 2, name.length)}.${ext}`;
    };

    const defaultProcessingMessage = 'Processing uploaded video...';
    const processingMessage = !!state.currentStatus
      ? {
          passed_nsfw_check: 'Processing video...',
          passed_video_processing: 'Getting ready to create songs...',
        }[state.currentStatus] || defaultProcessingMessage
      : defaultProcessingMessage;

    const [transactionLogger, setGenerationLogger] =
      useState<TransactionLogger>(() => createTransactionLogger());

    return isConfirmingClose ? (
      <>
        <span className='py-8 font-sans'>
          Are you sure you want to cancel? You might lose any unsaved changes.
        </span>
        <div className='mt-8 flex justify-end gap-2'>
          <button
            onClick={() => {
              setIsConfirmingClose?.(false);
              onClose?.();
            }}
            className='flex items-center justify-center rounded-md bg-quaternary px-10 py-3 text-sm font-medium text-primary hover:bg-black hover:text-primary'
            disabled={isLoading}
          >
            {isLoading ? <SpinnerSVG /> : 'Cancel Upload'}
          </button>
          <button
            onClick={() => {
              setIsConfirmingClose?.(false);
            }}
            className='flex items-center justify-center rounded-md bg-primary px-10 py-3 text-sm font-medium text-black hover:bg-black hover:text-primary'
            disabled={isLoading}
          >
            {isLoading ? <SpinnerSVG /> : 'Keep Working'}
          </button>
        </div>
      </>
    ) : (
      <div className='flex w-full flex-col gap-3'>
        {isAddingImage ? (
          <AddImageModalContent
            initialImageURL={initialImageURL}
            setAddingImageDataURL={setAddingImageDataURL}
            addingImageDataURL={addingImageDataURL}
            addingImageChanged={addingImageChanged}
            setAddingImageChanged={setAddingImageChanged}
            editedImagePrompt={editedImagePrompt}
            setEditedImagePrompt={setEditedImagePrompt}
            setInitialImageURL={setInitialImageURL}
            isGenerating={isGenerating}
            setIsGenerating={setIsGenerating}
            setIsAddingImage={setIsAddingImage}
            setAddedImages={setAddedImages}
            setS3Id={setS3Id}
            setCurrentImage={setCurrentImage}
            addedImages={addedImages}
            onClose={() => onClose?.()}
          />
        ) : isConfirmingTOS ? (
          <>
            <span
              className='font-sans'
              /*isChecked={isTOSConfirmed}
                        onChange={(e) => {
                          setIsTOSConfirmed(e.target.checked);
                        }}*/
            >
              I certify that I own or exclusively control all rights in any
              content I will upload using this Suno feature. I understand that I
              am not allowed to upload content if I do not own or exclusively
              control the rights to it, and that if I do so in spite of this
              prohibition, I will (among other problems) be breaching a contract
              with Suno and I may be subject to various other forms of legal
              liability as well. By clicking this box, I acknowledge and agree
              to the foregoing.
            </span>

            <Button
              className='mb-4'
              variant={ButtonVariant.Primary}
              onClick={() => {
                transactionLogger.logWebUserEvent({
                  actionName: 'GenerateFromVideoAgreeToTermsClicked',
                });

                if (storageAvailable('localStorage')) {
                  localStorage.setItem(
                    AUDIO_UPLOAD_TOS_STORAGE_KEY,
                    new Date().toString()
                  );
                }
                setIsLoading(true);
                if (state.uploadClipMetadata) {
                  onFinish?.(
                    state.uploadId,
                    editedTitle,
                    currentImage || '',
                    state.uploadType,
                    state.uploadClipMetadata?.s3_id || null,
                    transactionLogger
                  );
                }
              }}
              disabled={isLoading}
              icon={isLoading && <SpinnerSVG />}
            >
              Agree to Terms
            </Button>
          </>
        ) : (
          <>
            {state.uploadedFilename && !state.error && !state.isProcessing ? (
              <>
                <div className='h-auto w-full bg-white/20 p-6'>
                  <div className='flex flex-row'>
                    <AudioFileIcon className='h-7 w-7 text-pumpkin-600' />
                    <p className='mx-4 mb-4 font-sans'>
                      {truncateFilename(state.uploadedFilename)}
                    </p>
                    <div className='flex flex-1 flex-row-reverse'>
                      <Button
                        className='-mt-2'
                        variant={ButtonVariant.LightGlass}
                        shape={ButtonShape.Pill}
                        size={ButtonSize.Small}
                        icon={CloseIcon}
                        aria-label='Reset upload form'
                        onClick={() => {
                          const fileId = state.uppy.getFiles()?.[0]?.id;
                          if (fileId) {
                            state.uppy.removeFile(fileId);
                          }
                          state.uploadId = null;
                          state.uploadedFilename = null;
                          state.uploadClipMetadata = undefined;
                          state.error = null;
                          state.isProcessing = false;
                        }}
                      />
                    </div>
                  </div>
                  <div className='h-[3px] w-full bg-accent-orange'></div>
                </div>
                <div>
                  <EditClipMetadataForm
                    clipId={clipId}
                    editedTitle={editedTitle}
                    setEditedTitle={setEditedTitle}
                    currentImage={currentImage}
                    setCurrentImage={setCurrentImage}
                    continuedClips={continuedClips}
                    addedImages={addedImages}
                    audioUploadClipMetadata={state.uploadClipMetadata}
                    currentLyrics={currentLyrics}
                    setCurrentLyrics={setCurrentLyrics}
                    showDisplayTagsIfNeeded={false}
                  />
                </div>
              </>
            ) : (
              <>
                <Dashboard
                  width='100%'
                  height={280}
                  theme='dark'
                  proudlyDisplayPoweredByUppy={false}
                  uppy={state.uppy}
                  plugins={['Video']}
                />
                <span className='font-sans text-sm'>
                  MP4, MOV, AVI, MKV, WMV, WEBM supported
                </span>
              </>
            )}
            {state.isProcessing ? (
              <>
                <div className='my-4 flex'>
                  <SpinnerSVG className='mr-3' />
                  <p className='font-sans'>{processingMessage}</p>
                </div>
              </>
            ) : null}
            {state.error && (
              <div className='my-4 flex'>
                <p className='font-sans text-xs text-accent-error-on-primary'>
                  {state.error}
                </p>
              </div>
            )}
            <div className='mb-4 flex flex-row-reverse gap-2'>
              <button
                onClick={() => {
                  const transactionLogger = createTransactionLogger();
                  setGenerationLogger(transactionLogger);
                  transactionLogger.logWebUserEvent({
                    actionName: 'GenerateFromVideoClicked',
                  });
                  if (
                    storageAvailable('localStorage')
                      ? localStorage.getItem(AUDIO_UPLOAD_TOS_STORAGE_KEY)
                      : undefined
                  ) {
                    setIsLoading(true);
                    if (state.uploadClipMetadata) {
                      onFinish?.(
                        state.uploadId,
                        editedTitle,
                        currentImage || '',
                        state.uploadType,
                        state.uploadClipMetadata?.s3_id || null,
                        transactionLogger
                      );
                    }
                  } else {
                    setIsConfirmingTOS(true);
                  }
                }}
                className='flex cursor-pointer items-center justify-center rounded-md bg-quaternary px-10 py-3 text-sm font-medium text-primary hover:bg-tertiary hover:text-primary'
                disabled={
                  !state.uploadId ||
                  !state.uploadClipMetadata ||
                  state.isProcessing ||
                  !currentImage ||
                  !!state.error
                }
              >
                {isLoading ? <SpinnerSVG /> : 'Continue'}
              </button>

              {onClose && (
                <button
                  onClick={() => {
                    if (state.error) {
                      state.uploadId = null;
                      state.uppy.cancelAll();
                      state.error = null;
                      state.setShouldConfirmClose?.(false);
                      return;
                    }
                    onClose();
                  }}
                  className='flex cursor-pointer items-center justify-center rounded-md bg-quaternary px-10 py-3 text-sm font-medium text-primary hover:bg-tertiary hover:text-primary'
                >
                  {isLoading ? (
                    <SpinnerSVG />
                  ) : state.error ? (
                    'Retry'
                  ) : (
                    'Cancel'
                  )}
                </button>
              )}
            </div>
          </>
        )}
      </div>
    );
  }
);

export default UploadWrapper;
