'use client';

import { observer } from 'mobx-react-lite';
import { usePathname } from 'next/navigation';
import React, {
  createContext,
  useContext,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import { useEditModeTracking } from '@/app/(root)/edit/[slug]/useEditModeTracking';
import { Clip } from '@/state/clipStore';

interface TimeRange {
  start: number;
  end: number;
}

interface PreviewContextType {
  previewClip: Clip | null;
  setPreviewClip: React.Dispatch<React.SetStateAction<Clip | null>>;
  previewInfillRange: TimeRange | null;
  setPreviewInfillRange: React.Dispatch<React.SetStateAction<TimeRange | null>>;
  clipForSongRecs: Clip | null;
  setClipForSongRecs: React.Dispatch<React.SetStateAction<Clip | null>>;
  allowFlushToTop: boolean;
  setAllowFlushToTop: React.Dispatch<React.SetStateAction<boolean>>;
}

const PreviewContext = createContext<PreviewContextType>(undefined as never);

export const PreviewProvider: React.FC<React.PropsWithChildren> = observer(
  (props) => {
    const {
      clips: clipsStore,
      edit: editStore,
      genForm: createStore,
      playbar: playbarStore,
    } = useStores();

    const pathname = usePathname();

    const { logStartEditModeSession, logEndEditModeSession } =
      useEditModeTracking();

    const [previewInfillRange, setPreviewInfillRange] =
      useState<TimeRange | null>(null);
    const [clipForSongRecs, setClipForSongRecs] = useState<Clip | null>(null);
    const [allowFlushToTop, setAllowFlushToTop] = useState<boolean>(false);
    const [previewClip, setPreviewClip] = useState<Clip | null>(null);

    const lastPathname = useRef<string | null>(null);

    /**
     * Edit mode tracking
     */
    useEffect(() => {
      if (pathname === lastPathname.current) {
        return;
      }
      lastPathname.current = pathname;

      if (
        pathname.startsWith('/edit/') ||
        pathname.startsWith('/edit-legacy/')
      ) {
        editStore.initializeSession();
        logStartEditModeSession();
      } else if (editStore.isEditSessionActive) {
        editStore.isEditSessionActive = false;
        editStore.incrementActionIndex();
        editStore.resetEditState();
        createStore.resetInfill();
        setPreviewInfillRange(null);
        logEndEditModeSession();
      }
    }, [
      pathname,
      editStore,
      createStore,
      logStartEditModeSession,
      logEndEditModeSession,
    ]);

    /**
     * Set initial preview clip from playbar
     */
    const playbarClip =
      (playbarStore.clip?.id && clipsStore.clipById[playbarStore.clip?.id]) ||
      null;
    const hasSeenFirstClip = useRef(false);
    useEffect(() => {
      if (playbarClip) {
        // Skip setPreviewClip on init playbar load, to validate in dev disable reactStrictMode
        // TODO: decouple playbar from previewClip and make the right sidebar a user setting
        if (!hasSeenFirstClip.current) {
          hasSeenFirstClip.current = true;
          return;
        }
        setPreviewClip(playbarClip);
      }
    }, [playbarClip]);

    const contextValue = useMemo(
      () => ({
        previewClip,
        setPreviewClip,
        previewInfillRange,
        setPreviewInfillRange,
        clipForSongRecs,
        setClipForSongRecs,
        allowFlushToTop,
        setAllowFlushToTop,
      }),
      [
        previewClip,
        setPreviewClip,
        previewInfillRange,
        setPreviewInfillRange,
        clipForSongRecs,
        setClipForSongRecs,
        allowFlushToTop,
        setAllowFlushToTop,
      ]
    );

    return (
      <PreviewContext.Provider value={contextValue}>
        {props.children}
      </PreviewContext.Provider>
    );
  }
);

export function usePreviewContext() {
  return useContext(PreviewContext);
}
