import "reflect-metadata";
import { Preview } from "@storybook/react";
import {
  ensureKosMockBoot,
  ErrorBoundaryWithFallback,
  KosTranslationProvider,
  LoadingMessage,
} from "@kosdev-code/kos-ui-sdk";
import { ElementType, Suspense } from "react";
import { MemoryRouter } from "react-router";
import { KosCoreContextProvider } from "./registration";

// Webpack's require.context, typed here so the preview needs no @types/webpack-env.
const locales = (
  require as unknown as {
    context(
      dir: string,
      deep: boolean,
      filter: RegExp
    ): { keys(): string[]; (key: string): Record<string, unknown> };
  }
).context("../src/assets/locales", true, /\.json$/);

// The device serves the plugin's translations only once its KAB is deployed, so the
// preview serves them from source and leaves every other namespace to the device.
const bundleResolver = async (namespace: string, locale: string) => {
  const key = `./${locale}/${namespace}.json`;
  return locales.keys().includes(key)
    ? locales(key)
    : { fallback: true as const };
};

// Storybook applies the last decorator outermost.
export const decorators = [
  (Story: ElementType) => (
    <MemoryRouter initialEntries={["/"]}>
      <ErrorBoundaryWithFallback>
        <Suspense fallback={<LoadingMessage />}>
          <KosCoreContextProvider>
            <KosTranslationProvider bundleResolver={bundleResolver}>
              <Suspense>
                <Story />
              </Suspense>
            </KosTranslationProvider>
          </KosCoreContextProvider>
        </Suspense>
      </ErrorBoundaryWithFallback>
    </MemoryRouter>
  ),
  // A story's parameters.kosMock boots the preview with those KosMock switches.
  (Story: ElementType, { parameters }: { parameters: Record<string, any> }) =>
    ensureKosMockBoot(parameters.kosMock) ? null : <Story />,
];

const preview: Preview = {};

export default preview;
