'use client';

import { memo, useEffect } from 'react';
import { createStoreUpdater } from 'zustand-utils';

import { hasMeaningfulEditorContent } from '@/libs/editor/hasMeaningfulEditorContent';
import { documentHistoryQueueService } from '@/services/documentHistoryQueue';
import { useDocumentStore } from '@/store/document';
import { pageSelectors, usePageStore } from '@/store/page';
import { pageAgentRuntime } from '@/store/tool/slices/builtin/executors/lobe-page-agent';

import { type PublicState } from './store';
import { usePageEditorStore, useStoreApi } from './store';
import { useDocumentLock } from './useDocumentLock';
import { usePageDraft } from './usePageDraft';
import { useResourceEvents } from './useResourceEvents';

type PageAgentEditor = NonNullable<Parameters<typeof pageAgentRuntime.setEditor>[0]>;

export interface StoreUpdaterProps extends Partial<PublicState> {
  pageId?: string;
}

/**
 * StoreUpdater syncs PageEditorStore props and connects to page agent runtime.
 *
 * Note: Document content loading is handled by EditorCanvas via DocumentStore.
 * Title/emoji are consumed from PageEditorStore (set via setCurrentTitle/setCurrentEmoji).
 */
const StoreUpdater = memo<StoreUpdaterProps>(
  ({
    pageId,
    knowledgeBaseId,
    metaReadOnly,
    onDocumentIdChange,
    onEmojiChange,
    onSave,
    onTitleChange,
    onDelete,
    onBack,
    parentId,
    title,
    emoji,
  }) => {
    const storeApi = useStoreApi();
    const useStoreUpdater = createStoreUpdater(storeApi);

    const editor = usePageEditorStore((s) => s.editor);
    const initMeta = usePageEditorStore((s) => s.initMeta);
    const pageAgentEditor = editor as unknown as PageAgentEditor | undefined;
    // Workspace pages are view-first; resolve once here so the lock + gating read
    // a single source of truth.
    const isWorkspacePage = usePageStore((s) =>
      Boolean(pageSelectors.getDocumentById(pageId)(s)?.workspaceId),
    );

    // Drive the collaborative edit lock for workspace pages
    useDocumentLock();
    // Subscribe to realtime doc/lock events so the page syncs without polling
    useResourceEvents();
    // Snapshot unsaved content to sessionStorage while the lock is degraded so
    // an accidental refresh during a network blip doesn't blow away typing.
    usePageDraft();

    // Update store with props
    useStoreUpdater('documentId', pageId);
    useStoreUpdater('isWorkspacePage', isWorkspacePage);
    useStoreUpdater('knowledgeBaseId', knowledgeBaseId);
    useStoreUpdater('metaReadOnly', metaReadOnly);
    useStoreUpdater('onDocumentIdChange', onDocumentIdChange);
    useStoreUpdater('onEmojiChange', onEmojiChange);
    useStoreUpdater('onSave', onSave);
    useStoreUpdater('onTitleChange', onTitleChange);
    useStoreUpdater('onDelete', onDelete);
    useStoreUpdater('onBack', onBack);
    useStoreUpdater('parentId', parentId);

    // Initialize meta (title/emoji) with dirty tracking
    useEffect(() => {
      initMeta(title, emoji);
    }, [pageId, title, emoji, initMeta]);

    // Connect editor to page agent runtime
    useEffect(() => {
      if (pageAgentEditor) {
        pageAgentRuntime.setEditor(pageAgentEditor);
      }
      return () => {
        pageAgentRuntime.setEditor(null);
      };
    }, [pageAgentEditor]);

    // Connect title handlers and document ID to page agent runtime
    useEffect(() => {
      const titleGetter = () => {
        return storeApi.getState().title || '';
      };

      pageAgentRuntime.setCurrentDocId(pageId);
      pageAgentRuntime.setTitleHandlers(storeApi.getState().setTitle, titleGetter);
      pageAgentRuntime.setBeforeMutateHandler(() => {
        const editor = storeApi.getState().editor;
        const editorData = editor?.getDocument('json');

        if (!hasMeaningfulEditorContent(editorData)) {
          return;
        }

        documentHistoryQueueService.enqueueEditorSnapshot({
          documentId: pageId,
          editor,
          // Forward the page lock owner so the holder's pre-mutation snapshot
          // isn't rejected by its own lease (see saveDocumentHistory guard).
          lockOwnerId: pageId
            ? useDocumentStore.getState().documents[pageId]?.lockOwnerId
            : undefined,
        });
      });
      pageAgentRuntime.setAfterMutateHandler(async () => {
        if (!pageId) return;

        await useDocumentStore.getState().commitEditorMutation(pageId, { saveSource: 'llm_call' });
      });

      return () => {
        pageAgentRuntime.setCurrentDocId(undefined);
        pageAgentRuntime.setAfterMutateHandler(null);
        pageAgentRuntime.setTitleHandlers(null, null);
        pageAgentRuntime.setBeforeMutateHandler(null);
        void documentHistoryQueueService.flush();
      };
    }, [pageId, storeApi]);

    return null;
  },
);

export default StoreUpdater;
