'use client';

import { observer } from 'mobx-react-lite';
import { useContext, useState } from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import { ButtonVariant } from '@/components/button/Button';
import { ModalTypes } from '@/components/modal/constants/ModalTypes';
import ConfirmationModal from '@/components/modal/publishSong/ConfirmationModal';
import { ModalHeader } from '@/components/modal/publishSong/ModalHeader';
import {
  CancelButton,
  PublishButton,
  SaveButton,
} from '@/components/modal/publishSong/PublishFooterButtons';
import PublishModalEditClipSection, {
  PublishModalEditClipSectionProps,
} from '@/components/modal/publishSong/PublishModalEditClipSection';
import PublishModalFooter from '@/components/modal/publishSong/PublishModalFooter';
import { showPublicSongToast } from '@/components/modal/publishSong/publishSongToasts';
import { toast } from '@/components/toast/Toast';
import { useModalContext } from '@/context/ModalContext';
import ContestClipContext from '@/hooks/useContestClip';
import SongModalContext from '@/hooks/useSongModal';
import { PublishSongModaSaveEventProps } from '@/logging/eventTypes/PublishSongEventType';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { Clip } from '@/state/clipStore';

export const PublishMainContentScreen = observer(
  ({
    onClose,
    onSave,
    editClipMetadataFormProps,
    shouldDisableSave,
    clip,
    publishSongModalEventProps,
    shouldShowConfirmationModal,
    isPinned,
    hasPinnedChanged,
    hasSubmitToContestChanged,
    isUploading,
    submitToContest,
  }: {
    onClose: () => void;
    onSave: () => Promise<{ success: boolean; error?: any; data?: any }>;
    editClipMetadataFormProps: PublishModalEditClipSectionProps;
    shouldDisableSave: boolean;
    clip?: Clip;
    publishSongModalEventProps: PublishSongModaSaveEventProps;
    shouldShowConfirmationModal: boolean;
    isPinned: boolean;
    hasPinnedChanged: boolean;
    hasSubmitToContestChanged: boolean;
    isUploading: boolean;
    submitToContest: boolean;
  }) => {
    const [isSaving, setIsSaving] = useState(false);
    const [isPublishing, setIsPublishing] = useState(false);
    const { clips, session } = useStores();
    const { openModalWithData } = useModalContext();
    const [isConfirmingClose, setIsConfirmingClose] = useState(false);

    const { title, modalType, navigateTo } = useContext(SongModalContext);
    const { isContestEligible, isContestSubmission } =
      useContext(ContestClipContext);
    const isOwner = session.user?.id === clip?.user_id;
    const isContestSubmissionForSave = Boolean(
      hasSubmitToContestChanged && clip?.is_public
    );

    const handleSave = async () => {
      if (!clip) {
        return;
      }
      setIsSaving(true);
      logWebUserEvent({
        actionName: 'PublishSongModalSaveClicked',
        principalObjectType: 'song',
        principalObjectValue: clip.id,
        context: {
          ...publishSongModalEventProps,
        },
      });
      const result = await onSave();
      if (result.success) {
        if (hasPinnedChanged) {
          await clips.pinClipToProfile({
            clipId: clip.id,
            ...(hasSubmitToContestChanged && {
              submitToContest,
            }),
          });
          // This case should only be hit in the Song details modal (not publish) since clip will already be public
          // also, submitToContest should always be true since the toggle is disabled if it's already true -> hasSubmitToContestChanged should always be false
        } else if (isContestSubmissionForSave) {
          await clips.setClipVisibility({
            clipId: clip.id,
            isPublic: true,
            submitToContest,
          });
        }
        toast({
          title: 'Your song details have been updated.',
          status: 'info',
          duration: 5000,
          isClosable: true,
        });
      }
      setIsSaving(false);
      // show share screen if this is a contest submission from save, skip closing the modal
      if (isContestSubmissionForSave) {
        navigateTo('shareContestSubmission');
      } else {
        if (modalType === ModalTypes.UPDATE_CLIP_METADATA) {
          onClose();
        }
      }
    };

    const handlePublish = async () => {
      if (!clip) {
        return;
      }
      logWebUserEvent({
        actionName: 'PublishSongModalPublishClicked',
        principalObjectType: 'song',
        principalObjectValue: clip.id,
        context: {
          ...publishSongModalEventProps,
        },
      });

      setIsPublishing(true);
      //   Run these sequentially because clips.setMetadata in onSave can overwrite the visibility val
      const result = await onSave();
      if (result.success) {
        if (isPinned) {
          await clips.pinClipToProfile({
            clipId: clip.id,
            submitToContest,
          });
        } else {
          await clips.setClipVisibility({
            clipId: clip.id,
            isPublic: true,
            submitToContest,
          });
        }

        // Show post-submit share modal
        if (submitToContest && isContestSubmission({ clip })) {
          navigateTo('shareContestSubmission');
        } else {
          onClose();
          showPublicSongToast({ clip, session, openModalWithData });
        }
      }

      setIsPublishing(false);
    };

    const handleClose = () => {
      if (shouldShowConfirmationModal) {
        setIsConfirmingClose(true);
      } else {
        onClose();
      }
    };

    const handleConfirmClose = () => {
      setIsConfirmingClose(false);
      onClose();
    };

    return !isOwner ? null : (
      <div className='flex h-full w-full flex-col justify-between gap-2'>
        <div className='flex flex-col'>
          <ModalHeader onClose={handleClose} title={title} />
          <PublishModalEditClipSection {...editClipMetadataFormProps} />
          {isConfirmingClose && (
            <ConfirmationModal
              onCancel={() => setIsConfirmingClose(false)}
              onConfirm={handleConfirmClose}
            />
          )}
        </div>
        <PublishModalFooter>
          {modalType === ModalTypes.PUBLISH_SONG ? (
            <>
              <SaveButton
                disabled={shouldDisableSave || isSaving}
                onSave={handleSave}
                isSaving={isSaving}
                variant={ButtonVariant.Standard}
                isSubmittingToContest={false}
              />

              <PublishButton
                onPublish={handlePublish}
                isPublishing={isPublishing}
                disabled={isUploading || isPublishing}
                isSubmittingToContest={
                  submitToContest && isContestEligible({ clip })
                }
              />
            </>
          ) : (
            <>
              <CancelButton onCancel={handleClose} />
              <SaveButton
                disabled={shouldDisableSave || isSaving}
                onSave={handleSave}
                isSaving={isSaving}
                isSubmittingToContest={isContestSubmissionForSave}
              />
            </>
          )}
        </PublishModalFooter>
      </div>
    );
  }
);

export default PublishMainContentScreen;
