import { getEventSenderMetadata, type Logger } from '@learnitive/base-utils';
import type { ThemeManager } from '@learnitive/color-scheme-manager';
import { commandHandlers } from '@learnitive/command-handlers';
import { learnitiveAppCommands } from '@learnitive/commands';
import type { Services } from '@learnitive/context';
import type { EditorSaveCoordinator } from '@learnitive/editor';

import type {
  BaseServiceCommonOptions,
  RootEmitter,
  Store,
} from '@learnitive/types';
import { initializeServices as initializeServices2 } from './initialize-services';

export {
  createEditorSaveCoordinator,
  type EditorSaveCoordinator,
} from '@learnitive/editor';
export { readEditorEngineFromUrl } from './initialize-services';

export function initializeServices(
  logger: Logger,
  rootEmitter: RootEmitter,
  store: Store,
  theme: ThemeManager,
  abortSignal: AbortSignal,
  editorSaveCoordinator: EditorSaveCoordinator,
): Promise<Services> {
  const commonOpts: BaseServiceCommonOptions = {
    logger,
    store,
    rootAbortSignal: abortSignal,
    emitAppError(error) {
      rootEmitter.emit('event::error:uncaught-error', {
        error,
        isAppError: true,
        isRejection: false,
        isFakeThrow: true,
        sender: getEventSenderMetadata({ tag: 'initialize-service' }),
      });
    },
  };

  const services = initializeServices2(
    commonOpts,
    rootEmitter,
    learnitiveAppCommands,
    commandHandlers,
    theme,
    editorSaveCoordinator,
  );

  return services.mountAll().then(() => {
    const core = services.coreServices;

    // R4 feasibility certification only. The hook is deliberately query-gated
    // so no Live Draft control or service surface is exposed during normal use.
    // It lets the release E2E suite exercise the real browser BusyTeX worker
    // and inspect only the structured probe result.
    if (
      typeof window !== 'undefined' &&
      new URLSearchParams(window.location.search).get('learnitiveLiveDraftProbe') ===
        '1'
    ) {
      const target = window as unknown as {
        __learnitiveLiveDraftProbe?: {
          probe: (wsName: string) => ReturnType<typeof core.projectLiveDraft.probe>;
          cancel: () => void;
        };
      };
      target.__learnitiveLiveDraftProbe = {
        probe: (wsName) => core.projectLiveDraft.probe(wsName),
        cancel: () => core.projectLiveDraft.cancel(),
      };
    }

    return { core };
  });
}
