import styled from '@emotion/styled';
import { omit, uniq } from 'lodash-es';
import { observer } from 'mobx-react-lite';
import { Fragment, useCallback, useEffect, useRef, useState } from 'react';
import { useLocalStorage } from 'usehooks-ts';

import { useStores } from '@/app/(root)/AppProviders';
import StemSplitContext from '@/app/(root)/stems/StemSplitContext';
import StudioContext from '@/components/studio/StudioContext';
import { toast } from '@/components/toast/Toast';
import { useBreakpointMd } from '@/hooks/useBreakpoint';
import { fetchClip } from '@/hooks/useClip';
import { useContext, useContextSelector } from '@/hooks/useContextSelector';
import {
  ArrowDownIcon,
  ArrowUpIcon,
  EditIcon,
  EditRedoIcon,
  EditUndoIcon,
  MoreVerticalIcon,
  StemsIcon,
  StudioIcon,
} from '@/icons';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { Clip } from '@/state/clipStore';
import { FeatureKey, PlanFeature } from '@/state/sessionStore';
import { getClipTitle } from '@/utils/clip';
import ctrlStr from '@/utils/ctrlStr';
import { isMobileBrowser } from '@/utils/device';
import { isDev, isStaging } from '@/utils/environment';
import { isFeatureEnabledForPlan } from '@/utils/session';

import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '../button/Button';
import {
  ContextMenu,
  ContextMenuItem,
  ContextMenuTrigger,
} from '../contextMenu/ContextMenu';
import { ModelList } from '../edit2025/EditHeader';
import CanvasRenderer from '../edit2025/canvasRenderer/CanvasRenderer';
import ScrollCatcher from '../edit2025/canvasRenderer/ScrollCatcher';
import { CanvasRendererContainer } from '../edit2025/components';
import { getDownbeatsFromTiming } from '../edit2025/getTimingFromDownbeats';
import { AutomationPoint } from '../edit2025/types';
import Link from '../link/Link';
import Modal from '../modal/Modal';
import { ModalTypes } from '../modal/constants/ModalTypes';
import {
  Divider,
  HorizontalPanelGroup,
  Panel,
  VerticalPanelGroup,
} from '../panelSystem/PanelSystem';
import SpinnerSVG from '../svg/SpinnerSVG';
import { Tooltip } from '../tooltip/Tooltip';
import EditV3TimelineDroppable from './EditV3TimelineDroppable';
import EditV3Transport from './EditV3Transport';
import { HintMessage } from './HintMessage';
import LoadingOverlay from './LoadingOverlay';
import MagicStudioButton from './MagicStudioButton';
import MobileStudioFallback from './MobileStudioFallback';
import SaveIndicator from './SaveIndicator';
import StudioContextMenuContents from './StudioContextMenuContents';
import StudioEditToolbar from './StudioEditToolbar';
import StudioLyricsCorrectionForm from './StudioLyricsCorrectionForm';
import StudioModelTierPicker from './StudioModelTierPicker';
import StudioNotification from './StudioNotification';
import {
  ThickGapHorizontalDivider,
  ThickGapVerticalDivider,
  collapsedTrackHeadersPanelSize,
  headerPanelSize,
  oneFRPanelSize,
  transportPanelSize,
} from './StudioPanelUtilities';
import { StudioProjectManagementContext } from './StudioProjectManagementContext';
import StudioSelectionFollower from './StudioSelectionFollower';
import StudioSelectionInteractions from './StudioSelectionInteractions';
import StudioSidebarPanel from './StudioSidebarPanel';
import WorkspaceTrigger from './WorkspaceTrigger';
import removeNonUploadedClips from './actions/removeNonUploadedClips';
import setTrackHeight from './actions/setTrackHeight';
import { getCanvasDebug } from './canvasDebug';
import makeClipCreationIntentRegions from './canvasRegions/makeClipCreationIntentRegions';
import makeClipGenerationWebglRegions from './canvasRegions/makeClipGenerationWebglRegions';
import makeGapRegions from './canvasRegions/makeGapRegions';
import { makeSectionBoundaryRegions } from './canvasRegions/makeSectionBoundaryRegions';
import makeSongFadeRegions from './canvasRegions/makeSongFadeRegions';
import makeStudioBaseRegion from './canvasRegions/makeStudioBaseRegion';
import makeStudioBeatGridRegion from './canvasRegions/makeStudioBeatGridRegion';
import makeStudioDragPreviewRegions from './canvasRegions/makeStudioDragPreviewRegions';
import makeStudioPlayheadRegion from './canvasRegions/makeStudioPlayheadRegion';
import makeStudioScrollbarRegion from './canvasRegions/makeStudioScrollbarRegions';
import makeStudioSelectionRegions from './canvasRegions/makeStudioSelectionRegions';
import makeStudioTimelineLoopRegions from './canvasRegions/makeStudioTimelineLoopRegions';
import makeStudioWaveformRegionsV2 from './canvasRegions/makeStudioWaveformRegionsV2';
import makeStudioClipRegions from './canvasRegions/studioClipRegions/makeStudioClipRegionsV2';
import { StudioGlassModule } from './components';
import makePanelSize from './makePanelSize';
import {
  getAllUsedClipIds,
  getDerivedTiming,
  getEffectivelyMutedTracks,
  getSongEndBeats,
  getSongStartBeats,
} from './selectors';
import trimState from './trimState';

const Wrapper = styled.div`
  position: relative;
  height: 100%;
  width: 100%;
  padding: 3px;
  max-height: 100svh;
`;

const ToolbarWrapper = styled.div`
  height: 100%;
  transition: opacity 0.4s;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 0 20px;
`;

const ToolbarSection = styled.div`
  display: flex;
  align-items: center;
  gap: 10px;
`;

const TitleWrapper = styled.div`
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  svg {
    opacity: 0.5;
  }

  &:hover {
    svg {
      opacity: 0.9;
    }
  }
`;

const ProjectTitle = styled.div`
  font-size: 20px;
`;

const ProjectTitleInput = styled.input`
  font-size: 20px;
  border: none;
  background: none;
  color: inherit;
  min-width: 300px;
`;

const TimelineAndBrowserWrapper = styled.div`
  height: 100%;
`;

const TimelineWrapper = styled(StudioGlassModule)`
  height: 100%;
  overflow: hidden;
  border-radius: 10px;
  background-color: var(--color-background-primary);
  position: relative;
`;

const TransportWrapper = styled.div``;

const TrackSection = styled.div`
  background-color: var(--color-background-primary);
  display: grid;
  min-height: 0;
  height: 100%;
  grid-template-rows: 1fr;
`;

const TrackHeaders = styled.div`
  height: 100%;
  min-height: 0;
  overflow-y: auto;
  > * {
    min-height: 0;
  }
`;

export default observer(function StudioTimeline() {
  const studioContext = useContext(StudioContext);
  const isSaving = useContextSelector(
    StudioProjectManagementContext,
    (ctx) => ctx.isSaving
  );
  const createAndSaveNewStudioProject = useContextSelector(
    StudioProjectManagementContext,
    (ctx) => ctx.createAndSaveNewStudioProject
  );
  const beatsToCanvasX = studioContext.beatsToCanvasX;
  const {
    frameCountRef,
    scrollXRef,
    pxPerBeatRef,
    handleScroll,
    handleZoom,
    wrapperRef,
    zoomAboutSelectionOrCenter,
  } = studioContext.timelineController;

  const { edit, session, project, menus } = useStores();

  const trackListRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    frameCountRef.current++;
  }, [frameCountRef]);

  const [rendering, setRendering] = useState(false);

  const getCanvasRegions = useCallback(() => {
    const wrapper = wrapperRef.current;
    const trackList = trackListRef.current;

    if (!wrapper || !trackList) {
      return [];
    }

    let lastAutomationPointX = -Infinity;
    const {
      aboveSelection: aboveSelectionClipRegions,
      belowGrid: belowGridClipRegions,
      belowGridLifted: belowGridLiftedClipRegions,
      belowSelection: belowSelectionClipRegions,
      belowSelectionLifted: belowSelectionLiftedClipRegions,
      previewClipRegions: previewClipRegions,
    } = makeStudioClipRegions(studioContext);

    const {
      aboveSelectionRegions: aboveSelectionGapRegions,
      belowSelectionRegions: belowSelectionGapRegions,
    } = makeGapRegions(studioContext);

    const timing = getDerivedTiming(studioContext.state);

    const { lines, shadedRegions, topSection } =
      makeStudioBeatGridRegion(studioContext);
    const {
      aboveRulerRegions: aboveRulerSelectionRegions,
      belowRulerRegions: belowRulerSelectionRegions,
    } = makeStudioSelectionRegions(studioContext);

    return [
      makeStudioBaseRegion(studioContext),
      shadedRegions,
      ...belowGridClipRegions,
      ...belowGridLiftedClipRegions,
      lines,
      ...(studioContext.mode === 'edit' && !matchingLyrics
        ? belowSelectionGapRegions
        : []),
      ...belowSelectionClipRegions,
      ...belowSelectionLiftedClipRegions,
      ...(studioContext.oneTrackMode ? makeSongFadeRegions(studioContext) : []),
      ...(studioContext.mode === 'edit' && !matchingLyrics
        ? makeSectionBoundaryRegions(studioContext)
        : []),
      ...belowRulerSelectionRegions,
      topSection,
      ...aboveRulerSelectionRegions,
      ...aboveSelectionClipRegions,
      ...(studioContext.mode === 'edit' && !matchingLyrics
        ? aboveSelectionGapRegions
        : []),
      ...makeStudioWaveformRegionsV2(
        studioContext.playbackController.dspContext,
        studioContext
      ),
      ...makeClipCreationIntentRegions(studioContext),
      ...makeStudioDragPreviewRegions(studioContext),
      ...makeStudioScrollbarRegion(studioContext),
      ...makeClipGenerationWebglRegions(studioContext),
      ...makeStudioTimelineLoopRegions(studioContext),
      ...previewClipRegions,
      makeStudioPlayheadRegion(studioContext),
      ...timing.bpsAutomation.map((point: AutomationPoint) => ({
        render: (ctx: CanvasRenderingContext2D) => {
          if (!getCanvasDebug()) return;
          const minBPM = timing.bpsAutomation.reduce(
            (min: number, point: AutomationPoint) => Math.min(min, point.value),
            Infinity
          );
          const maxBPM = timing.bpsAutomation.reduce(
            (max: number, point: AutomationPoint) => Math.max(max, point.value),
            -Infinity
          );
          ctx.fillStyle = 'white';
          const x = beatsToCanvasX(point.beats);
          const height = (30 * (point.value - minBPM)) / (maxBPM - minBPM);
          const y =
            studioContext.timelineController.getWrapperRect().height - height;
          ctx.fillRect(x, y, 3, height);
          if (x > lastAutomationPointX + 50) {
            ctx.fillText((point.value * 60).toFixed(0) + 'BPM', x, y - 10);
            lastAutomationPointX = x;
          }
        },
      })),
    ];
  }, [edit.editSessionId, studioContext, zoomAboutSelectionOrCenter]);

  const receiveScroll = useCallback(
    (x: number, y: number) => {
      handleScroll(x, y);
      trackListRef.current?.scrollBy(x, y);
    },
    [handleScroll]
  );

  const [editingTitle, setEditingTitle] = useState(false);
  const [title, setTitle] = useState(studioContext.state.title || '');

  const submitTitle = useCallback(() => {
    setEditingTitle(false);
    // bleh
    studioContext.setState((state) => ({ ...state, title }));
  }, [studioContext, title]);

  const [renderedClip, setRenderedClip] = useLocalStorage<Clip | null>(
    `edit-mode-rendered-clip-${studioContext.studioProjectId}-jun-2-2025`,
    null
  );

  const handleRender = useCallback(async () => {
    setRendering(true);
    try {
      const editedClip = studioContext.state.editClipId
        ? await fetchClip(
            studioContext.clipsStore,
            studioContext.state.editClipId
          )
        : null;
      const result = await edit.apiClient.POST('/api/studio/render-state', {
        body: {
          // note: do not pass from_studio_project_id here. that property is only intended for clips created from within the Studio UI, not for rendered outputs.
          title: `${studioContext.state.title || 'Untitled'} (Edit)`,
          lyrics:
            studioContext.lyricsEditController.getFullSongPlaintextLyrics(),
          tags: editedClip?.metadata.tags,
          negative_tags: editedClip?.metadata.negative_tags,
          style_summary: editedClip?.display_tags,
          caption: editedClip?.caption,
          state: trimState(
            removeNonUploadedClips(studioContext.state),
            getSongStartBeats(studioContext.state),
            getSongEndBeats(studioContext.state)
          ),
          start_beats: getSongStartBeats(studioContext.state),
          end_beats: getSongEndBeats(studioContext.state),
          project_id: project.currentProjectId,
          downbeats: getDownbeatsFromTiming(
            getDerivedTiming(studioContext.state),
            getSongStartBeats(studioContext.state),
            getSongEndBeats(studioContext.state)
          ),
          web_client_pathname: window.location.pathname,
        },
      });
      if ((result.data as any)?.moderation_error_message) {
        toast({
          title: 'Moderation error',
          description: (result.data as any).moderation_error_message,
          status: 'error',
          duration: 5000,
          isClosable: true,
        });
      } else if ((result.data as any)?.id) {
        setRenderedClip(result.data as Clip);
      }
    } catch (error) {
      console.error('error rendering clip', error);
    } finally {
      setRendering(false);
    }
  }, [studioContext]);

  const [confirmingReset, setConfirmingReset] = useState(false);
  const [resettingState, setResettingState] = useState(false);

  const stemSplitContext = useContext(StemSplitContext);

  const isMobile = !useBreakpointMd();
  const isMobileBrowserCheck = isMobileBrowser();

  const [matchingLyrics, setMatchingLyrics] = useState(false);

  const hasStudio = session.flags && Boolean(session.flags['studio']);

  const [creatingStudioProject, setCreatingStudioProject] = useState(false);

  if (
    studioContext.mode === 'edit' &&
    !isFeatureEnabledForPlan(session, PlanFeature.EditMode)
  ) {
    return (
      <div className='flex h-full items-center justify-center gap-2'>
        <Button href='/account' variant={ButtonVariant.Primary}>
          Subscribe to Pro
        </Button>
        to enable Song Editor.
      </div>
    );
  }

  if (
    studioContext.mode !== 'edit' &&
    !isFeatureEnabledForPlan(session, PlanFeature.Studio)
  ) {
    return (
      <div className='flex h-full items-center justify-center gap-2'>
        <Button href='/account' variant={ButtonVariant.Primary}>
          Subscribe to Premium
        </Button>
        to enable Studio.
      </div>
    );
  }

  if (isMobile || isMobileBrowserCheck) {
    return <MobileStudioFallback editClipId={studioContext.state.editClipId} />;
  }

  return (
    <Wrapper>
      {confirmingReset && (
        <Modal title='Are you sure?' onClose={() => setConfirmingReset(false)}>
          <div className='flex flex-col gap-4'>
            <p>
              This will clear all changes and return to the initial state of
              this song.
            </p>
            <div className='flex justify-end gap-2'>
              <Button onClick={() => setConfirmingReset(false)}>Cancel</Button>
              <Button
                onClick={async () => {
                  logWebUserEvent({
                    actionName: 'EditV3ResetAll',
                    context: {
                      editSessionId: studioContext.editSessionId,
                      editingClipId:
                        studioContext.state.editClipId ||
                        'MISSING_EDIT_CLIP_ID',

                      usedCrop: !!studioContext.state.metadata?.usedCrop,
                      usedReorder: !!studioContext.state.metadata?.usedReorder,
                      usedDuplicate:
                        !!studioContext.state.metadata?.usedDuplicate,
                      usedDelete: !!studioContext.state.metadata?.usedDelete,
                      usedSplit: !!studioContext.state.metadata?.usedSplit,
                      usedCreateSection:
                        !!studioContext.state.metadata?.usedCreateSection,
                      usedReplaceSection:
                        !!studioContext.state.metadata?.usedReplaceSection,
                      usedExtend: !!studioContext.state.metadata?.usedExtend,
                    },
                  });
                  setResettingState(true);
                  setConfirmingReset(false);
                  await studioContext.initializeStateForClip(true);
                  setResettingState(false);
                }}
              >
                Reset
              </Button>
            </div>
          </div>
        </Modal>
      )}

      <HintMessage />
      {studioContext.timelineController.contextMenuConfig && (
        <ContextMenu
          clientCoords={
            studioContext.timelineController.contextMenuConfig.clientCoords
          }
        >
          {
            <studioContext.timelineController.contextMenuConfig.ChildComponent
              {...studioContext.timelineController.contextMenuConfig.otherProps}
              onClose={() => {
                studioContext.timelineController.setContextMenuConfig(null);
              }}
            />
          }
        </ContextMenu>
      )}
      <VerticalPanelGroup>
        <Panel size={headerPanelSize}>
          <ToolbarWrapper>
            <ToolbarSection>
              <ContextMenuTrigger
                placement='bottom-right'
                ButtonComponent={(props) => (
                  <Button
                    variant={ButtonVariant.Tertiary}
                    size={ButtonSize.Small}
                    icon={<MoreVerticalIcon className='h-5 w-5' />}
                    {...props}
                  />
                )}
                ContentsComponent={({ onClose }) => (
                  <>
                    <ContextMenuItem>
                      <StudioModelTierPicker />
                    </ContextMenuItem>

                    {(isDev || isStaging) && (
                      <ModelList
                        models={session.getViewableModels()}
                        selectedModel={studioContext.modelOverride}
                        onSelect={(model) =>
                          studioContext.setModelOverride(
                            model.external_key || null
                          )
                        }
                      />
                    )}

                    <Tooltip
                      label={
                        studioContext.previewController.previewingOnTimeline
                          ? 'Previewing a clip. Press [ESC] to stop.'
                          : ''
                      }
                    >
                      <ContextMenuItem
                        disabled={
                          !!studioContext.previewController
                            .previewingOnTimeline ||
                          getDerivedTiming(studioContext.state).bpsAutomation
                            .length === 0
                        }
                        onClick={() => {
                          setMatchingLyrics(true);
                          onClose();
                        }}
                      >
                        Match Lyrics to Audio
                      </ContextMenuItem>
                    </Tooltip>
                  </>
                )}
              />
              {studioContext.mode === 'edit' ? (
                <>
                  <div
                    style={{
                      fontSize: 20,
                      position: 'relative',
                      display: 'block',
                    }}
                  >
                    Song Editor
                    <span className='relative -top-1 ml-1 inline-block rounded-md bg-gray-400 px-1.5 py-0.5 text-xs font-medium text-foreground-primary'>
                      Beta
                    </span>
                  </div>

                  {studioContext.state.editClipId && (
                    <Button
                      href={`/edit-legacy/${studioContext.state.editClipId}`}
                      variant={ButtonVariant.Tertiary}
                      className='text-sm text-gray-500 hover:underline'
                      onClick={() => {
                        logWebUserEvent({
                          actionName: 'EditV3ReturnToEditV2',
                          context: {
                            editSessionId: studioContext.editSessionId,
                            editingClipId:
                              studioContext.state.editClipId ||
                              'MISSING_EDIT_CLIP_ID',

                            usedCrop: !!studioContext.state.metadata?.usedCrop,
                            usedReorder:
                              !!studioContext.state.metadata?.usedReorder,
                            usedDuplicate:
                              !!studioContext.state.metadata?.usedDuplicate,
                            usedDelete:
                              !!studioContext.state.metadata?.usedDelete,
                            usedSplit:
                              !!studioContext.state.metadata?.usedSplit,
                            usedCreateSection:
                              !!studioContext.state.metadata?.usedCreateSection,
                            usedReplaceSection:
                              !!studioContext.state.metadata
                                ?.usedReplaceSection,
                            usedExtend:
                              !!studioContext.state.metadata?.usedExtend,
                          },
                        });
                      }}
                    >
                      Legacy Editor
                    </Button>
                  )}
                </>
              ) : (
                <Link href='/studio'>
                  <svg
                    width='161'
                    height='20'
                    viewBox='0 0 530 66'
                    fill='none'
                    xmlns='http://www.w3.org/2000/svg'
                  >
                    <path
                      d='M481.188 65.35C471.828 65.35 456.078 64.9 445.908 58.33C436.818 52.48 432.498 41.23 432.498 32.95C432.498 24.58 436.638 13.33 445.908 7.57001C456.078 1.27001 470.478 0.100006 481.278 0.100006C492.168 0.100006 505.668 1.27001 515.838 7.57001C525.018 13.24 529.428 24.67 529.428 32.95C529.428 41.23 524.928 52.57 515.838 58.33C505.668 64.81 490.548 65.35 481.188 65.35ZM481.008 45.55C484.698 45.55 490.458 45.46 494.418 42.85C497.838 40.6 499.638 36.28 499.638 33.13C499.638 29.89 497.838 25.57 494.418 23.32C490.548 20.8 484.698 20.8 481.098 20.8C477.498 20.8 471.378 20.89 467.418 23.32C463.908 25.48 462.288 29.89 462.288 33.13C462.288 36.28 463.908 40.6 467.418 42.85C471.378 45.37 477.408 45.55 481.008 45.55Z'
                      fill='white'
                    />
                    <path d='M397.384 1H428.884V64H397.384V1Z' fill='white' />
                    <path
                      d='M295.255 64.09V0.910004H349.165C358.165 0.910004 372.745 3.52 381.475 9.10001C389.755 15.04 392.005 23.77 392.005 32.5C392.005 40.69 389.125 50.05 381.475 55.63C372.745 62.02 358.615 64.09 349.165 64.09H295.255ZM326.665 43.57H345.565C348.895 43.57 353.845 42.85 356.905 40.6C359.605 38.71 360.595 35.38 360.595 32.5C360.595 29.44 359.785 26.38 356.905 24.31C353.845 22.33 348.715 21.43 345.565 21.43H326.665V43.57Z'
                      fill='white'
                    />
                    <path
                      d='M290.487 1L290.757 26.74C290.757 43.39 285.267 51.85 279.687 55.81C274.107 59.77 261.237 65.53 242.787 65.53C223.167 65.53 210.837 61.21 205.347 56.8C199.857 52.39 193.017 47.98 193.017 26.83V1H225.327L225.507 26.74C225.507 33.31 228.657 40.87 241.527 40.87C254.397 40.87 257.997 33.49 257.997 26.83L257.907 1H290.487Z'
                      fill='white'
                    />
                    <path
                      d='M190.359 1V25.3H163.719V64H127.719V25.3H100.359V1H190.359Z'
                      fill='white'
                    />
                    <path
                      d='M48.14 64.9C38.33 64.9 24.5601 65.17 15.29 60.31C5.12005 55 1.70005 49.06 1.70005 42.85H38.7801C39.4101 45.01 43.9101 46.99 48.7701 46.99C54.1701 46.99 59.0301 45.19 57.8601 43.3C56.5101 41.14 34.7301 41.59 22.49 40.78C7.01005 39.7 0.800049 32.14 0.800049 22.15C0.800049 14.05 4.67005 8.55998 16.46 3.60999C25.46 -0.170018 38.6901 0.0999829 48.5 0.0999829C58.3101 0.0999829 71.1801 -0.170019 80.4501 4.68998C90.62 9.99998 94.04 15.94 94.04 22.15H57.8601C57.2301 19.99 52.7301 18.01 48.4101 18.01C43.3701 18.01 37.7 19 38.7801 21.16C39.9501 23.5 60.38 23.41 76.1301 24.4C91.79 25.39 97.6401 32.68 97.6401 42.85C97.6401 50.95 94.9401 56.44 83.1501 61.39C74.1501 65.17 57.9501 64.9 48.14 64.9Z'
                      fill='white'
                    />
                  </svg>
                </Link>
              )}
            </ToolbarSection>
            {studioContext.mode === 'studio' && (
              <ToolbarSection>
                {!editingTitle && (
                  <TitleWrapper
                    className='flex items-center gap-2'
                    onClick={() => setEditingTitle(true)}
                  >
                    <ProjectTitle>
                      {studioContext.state.title || 'Untitled'}
                    </ProjectTitle>
                    <EditIcon />
                  </TitleWrapper>
                )}
                {editingTitle && (
                  <ProjectTitleInput
                    autoFocus
                    placeholder='Enter a project name'
                    value={title}
                    maxLength={100}
                    onChange={(e) => setTitle(e.target.value)}
                    onKeyDown={(e) => {
                      if (e.key === 'Enter') {
                        submitTitle();
                      }
                    }}
                    onBlur={() => {
                      submitTitle();
                    }}
                  />
                )}
              </ToolbarSection>
            )}
            <ToolbarSection>
              <Tooltip label='Undo all changes and reset to initial state'>
                <Button
                  variant={ButtonVariant.Secondary}
                  size={ButtonSize.Small}
                  shape={ButtonShape.Pill}
                  className='py-1'
                  icon={resettingState ? <SpinnerSVG /> : <EditUndoIcon />}
                  onClick={async () => {
                    setConfirmingReset(true);
                  }}
                >
                  Reset All
                </Button>
              </Tooltip>
              <Tooltip label={`Undo last change [${ctrlStr} Z]`}>
                <Button
                  icon={<EditUndoIcon />}
                  variant={ButtonVariant.Standard}
                  size={ButtonSize.Small}
                  shape={ButtonShape.Pill}
                  disabled={!studioContext.canUndo}
                  onClick={() => {
                    logWebUserEvent({
                      actionName: 'EditV3Undo',
                      context: {
                        editSessionId: studioContext.editSessionId,
                        editingClipId:
                          studioContext.state.editClipId ||
                          'MISSING_EDIT_CLIP_ID',
                        trigger: 'button',
                      },
                    });
                    studioContext.undo();
                  }}
                />
              </Tooltip>
              <Tooltip label={`Redo last change [${ctrlStr} Shift Z]`}>
                <Button
                  icon={<EditRedoIcon />}
                  variant={ButtonVariant.Standard}
                  size={ButtonSize.Small}
                  shape={ButtonShape.Pill}
                  disabled={!studioContext.canRedo}
                  onClick={() => {
                    logWebUserEvent({
                      actionName: 'EditV3Redo',
                      context: {
                        editSessionId: studioContext.editSessionId,
                        editingClipId:
                          studioContext.state.editClipId ||
                          'MISSING_EDIT_CLIP_ID',
                        trigger: 'button',
                      },
                    });
                    studioContext.redo();
                  }}
                />
              </Tooltip>
              <WorkspaceTrigger variant={ButtonVariant.Secondary} />

              <Button
                disabled={
                  rendering ||
                  getSongStartBeats(studioContext.state) ===
                    getSongEndBeats(studioContext.state)
                }
                shape={ButtonShape.Pill}
                className='py-1'
                onClick={() => {
                  logWebUserEvent({
                    actionName: 'EditV3SaveAsNewSong',
                    context: {
                      editSessionId: studioContext.editSessionId,
                      editingClipId:
                        studioContext.state.editClipId ||
                        'MISSING_EDIT_CLIP_ID',

                      usedCrop: !!studioContext.state.metadata?.usedCrop,
                      usedReorder: !!studioContext.state.metadata?.usedReorder,
                      usedDuplicate:
                        !!studioContext.state.metadata?.usedDuplicate,
                      usedDelete: !!studioContext.state.metadata?.usedDelete,
                      usedSplit: !!studioContext.state.metadata?.usedSplit,
                      usedCreateSection:
                        !!studioContext.state.metadata?.usedCreateSection,
                      usedReplaceSection:
                        !!studioContext.state.metadata?.usedReplaceSection,
                      usedExtend: !!studioContext.state.metadata?.usedExtend,

                      audibleClipIds: uniq(
                        studioContext.state.tracks
                          .filter(
                            (t) =>
                              t.amplitude > 0 &&
                              !getEffectivelyMutedTracks(studioContext.state)[
                                t.id
                              ]
                          )
                          .flatMap((t) => t.clips.map((c) => c.clipId))
                          .filter(Boolean) as string[]
                      ),
                    },
                  });
                  handleRender();
                }}
                icon={rendering ? <SpinnerSVG /> : null}
              >
                Save as New Song
              </Button>
              <Button
                variant={ButtonVariant.Standard}
                size={ButtonSize.Small}
                shape={ButtonShape.Pill}
                icon={<StemsIcon />}
                className='py-1'
                onClick={() => {
                  if (studioContext.state.editClipId) {
                    stemSplitContext?.setSplittingClipId(
                      studioContext.state.editClipId
                    );
                  }

                  logWebUserEvent({
                    actionName: 'EditV3GetStemsClicked',
                    context: {
                      editSessionId: studioContext.editSessionId,
                      editingClipId:
                        studioContext.state.editClipId ||
                        'MISSING_EDIT_CLIP_ID',
                    },
                  });
                }}
              >
                Get Stems
              </Button>
              {hasStudio && (
                <MagicStudioButton
                  disabled={creatingStudioProject}
                  icon={
                    creatingStudioProject ? (
                      <SpinnerSVG className='h-6 w-6' />
                    ) : (
                      <StudioIcon className='h-6 w-6' />
                    )
                  }
                  onClick={async () => {
                    if (!isFeatureEnabledForPlan(session, PlanFeature.Studio)) {
                      menus.setCurrentUpsellFeature(FeatureKey.STUDIO);
                      menus.openModal(ModalTypes.UPSELL_MODAL);
                      return;
                    }
                    setCreatingStudioProject(true);
                    try {
                      const stateWithoutEditClip = omit(
                        studioContext.state,
                        'editClipId'
                      );

                      stateWithoutEditClip.songFadeInBeats = 0;
                      stateWithoutEditClip.songFadeOutBeats = 0;

                      const id =
                        await createAndSaveNewStudioProject(
                          stateWithoutEditClip
                        );

                      logWebUserEvent({
                        actionName: 'CreatedNewStudioProject',
                        context: {
                          studioProjectId: id,
                          clipIds: getAllUsedClipIds(stateWithoutEditClip),
                          trigger: 'save_to_library',
                        },
                      });

                      window.location.href = `/studio?initial_project_id=${id}`;
                      logWebUserEvent({
                        actionName: 'NavigatedToStudio',
                        context: {
                          trigger: 'edit_v3_header',
                        },
                      });
                    } catch (e) {
                      console.error(e);
                      toast({
                        title: 'Error creating studio project',
                        description: 'Please try again later.',
                        status: 'error',
                      });
                      setCreatingStudioProject(false);
                    }
                  }}
                >
                  Edit in Studio
                </MagicStudioButton>
              )}
            </ToolbarSection>
          </ToolbarWrapper>
        </Panel>
        {matchingLyrics && (
          <>
            <Divider influence='neither'>
              <ThickGapHorizontalDivider transparent />
            </Divider>
            <Panel size={oneFRPanelSize}>
              <StudioLyricsCorrectionForm
                onClose={() => setMatchingLyrics(false)}
              />
            </Panel>
          </>
        )}
        <Divider influence='neither'>
          <ThickGapHorizontalDivider transparent />
        </Divider>
        <Panel size={matchingLyrics ? makePanelSize(200) : oneFRPanelSize}>
          <TimelineAndBrowserWrapper>
            <HorizontalPanelGroup animateSizeChanges={false}>
              {!matchingLyrics && (
                <>
                  <StudioSidebarPanel />
                  <Divider influence='both'>
                    <ThickGapVerticalDivider transparent />
                  </Divider>
                </>
              )}
              <Panel size={oneFRPanelSize}>
                <VerticalPanelGroup>
                  <Panel size={oneFRPanelSize}>
                    <TimelineWrapper
                      style={{
                        border: 'none',
                      }}
                    >
                      {renderedClip && (
                        <StudioNotification
                          title='Song Saved!'
                          content={
                            <>
                              <Link
                                href={`/song/${renderedClip.id}`}
                                target='_blank'
                              >
                                {getClipTitle(renderedClip)}
                              </Link>{' '}
                              was saved in your library.
                            </>
                          }
                          buttonContent='Go to Song'
                          href={`/song/${renderedClip.id}`}
                          onClose={() => {
                            setRenderedClip(null);
                          }}
                        />
                      )}

                      {studioContext.loading && <LoadingOverlay />}
                      {!matchingLyrics && <StudioEditToolbar />}
                      <HorizontalPanelGroup>
                        <Panel size={collapsedTrackHeadersPanelSize}>
                          <TrackSection
                            ref={
                              studioContext.timelineController
                                .trackHeaderListRef
                            }
                          >
                            <TrackHeaders
                              onWheel={() => frameCountRef.current++}
                              ref={trackListRef}
                            >
                              <VerticalPanelGroup frameCountRef={frameCountRef}>
                                {matchingLyrics ? (
                                  <Panel size={makePanelSize(35)} />
                                ) : (
                                  <Panel size={oneFRPanelSize} minSizePx={55} />
                                )}
                                <Divider
                                  influence={
                                    matchingLyrics ? 'neither' : 'after'
                                  }
                                >
                                  <ThickGapHorizontalDivider
                                    transparent
                                    className='rounded-lg'
                                  />
                                </Divider>
                                {studioContext.state.tracks.map((track) => (
                                  <Fragment key={track.id}>
                                    <Panel
                                      size={
                                        matchingLyrics
                                          ? makePanelSize(120)
                                          : makePanelSize(track.height)
                                      }
                                      minSizePx={52}
                                      debounceSetSizeMS={100}
                                      setSize={(size) =>
                                        studioContext.setState(
                                          setTrackHeight(track.id, size.count)
                                        )
                                      }
                                    >
                                      <div
                                        className='h-full'
                                        data-track-header={track.id}
                                        ref={
                                          studioContext.timelineController
                                            .receiveTrackHeader
                                        }
                                      >
                                        {!matchingLyrics && (
                                          <div className='flex h-full flex-col items-center justify-between rounded-lg bg-gray-100 text-gray-400 transition-all duration-200'>
                                            <ArrowUpIcon />
                                            <ArrowDownIcon />
                                          </div>
                                        )}
                                      </div>
                                    </Panel>
                                    <Divider
                                      influence={
                                        matchingLyrics ? 'neither' : 'before'
                                      }
                                    >
                                      <ThickGapHorizontalDivider
                                        transparent
                                        className='rounded-lg'
                                      />
                                    </Divider>
                                  </Fragment>
                                ))}
                                {matchingLyrics ? (
                                  <Panel size={makePanelSize(35)} />
                                ) : (
                                  <Panel
                                    size={oneFRPanelSize}
                                    minSizePx={330}
                                  />
                                )}
                              </VerticalPanelGroup>
                            </TrackHeaders>
                          </TrackSection>
                        </Panel>
                        <Panel size={oneFRPanelSize}>
                          <EditV3TimelineDroppable>
                            <CanvasRendererContainer
                              ref={
                                studioContext.timelineController
                                  .receiveWrapperRef
                              }
                              onContextMenu={(e) => {
                                e.preventDefault();
                                e.stopPropagation();

                                studioContext.timelineController.setContextMenuConfig(
                                  {
                                    ChildComponent: (props) => (
                                      <StudioContextMenuContents
                                        {...props}
                                        eventTrigger='right-click'
                                      />
                                    ),
                                    clientCoords: {
                                      top: e.clientY,
                                      left: e.clientX,
                                    },
                                  }
                                );
                              }}
                            >
                              <ScrollCatcher
                                onScroll={receiveScroll}
                                onZoom={handleZoom}
                                scrollXRef={scrollXRef}
                                pxPerBeatRef={pxPerBeatRef}
                                invertZoom={false} // TODO
                                zoomOnResize
                              >
                                <CanvasRenderer
                                  getCanvasRegions={getCanvasRegions}
                                  frameCountRef={frameCountRef}
                                  withWebGL={true}
                                  allowRightClicks={true}
                                />
                                {!studioContext.timelineController
                                  .contextMenuConfig &&
                                  !matchingLyrics &&
                                  studioContext.state.selection.anchorBeats >
                                    -5000 && (
                                    <StudioSelectionFollower>
                                      <StudioSelectionInteractions />
                                    </StudioSelectionFollower>
                                  )}
                              </ScrollCatcher>
                            </CanvasRendererContainer>
                          </EditV3TimelineDroppable>
                        </Panel>
                      </HorizontalPanelGroup>
                      <SaveIndicator isSaving={isSaving} />
                    </TimelineWrapper>
                  </Panel>
                </VerticalPanelGroup>
              </Panel>
            </HorizontalPanelGroup>
          </TimelineAndBrowserWrapper>
        </Panel>
        <Divider influence='neither'>
          <ThickGapHorizontalDivider transparent />
        </Divider>
        <Panel size={transportPanelSize}>
          <TransportWrapper>
            <EditV3Transport />
          </TransportWrapper>
        </Panel>
      </VerticalPanelGroup>
    </Wrapper>
  );
});
