import { createContext, type ReactNode, useContext, useMemo } from "react";
import type {
  EffectiveViewProjection,
  PlatformViewSurface,
  PlatformWebModule
} from "../types";
import {
  isViewSurfaceVisible,
  viewSurfaceCatalogueForModules
} from "./views";

type ViewContextValue = {
  projection: EffectiveViewProjection | null;
  surfaces: PlatformViewSurface[];
  isVisible: (surfaceId: string | null | undefined) => boolean;
};

const ViewContext = createContext<ViewContextValue>({
  projection: null,
  surfaces: [],
  isVisible: () => true
});

export function PlatformViewProvider({
  modules,
  projection,
  children
}: {
  modules: PlatformWebModule[];
  projection: EffectiveViewProjection | null;
  children: ReactNode;
}) {
  const surfaces = useMemo(
    () => viewSurfaceCatalogueForModules(modules),
    [modules]
  );
  const value = useMemo<ViewContextValue>(
    () => ({
      projection,
      surfaces,
      isVisible: (surfaceId) =>
        isViewSurfaceVisible(projection, surfaceId, surfaces)
    }),
    [projection, surfaces]
  );
  return <ViewContext.Provider value={value}>{children}</ViewContext.Provider>;
}

export function useEffectiveView(): EffectiveViewProjection | null {
  return useContext(ViewContext).projection;
}

export function useViewSurfaces(): PlatformViewSurface[] {
  return useContext(ViewContext).surfaces;
}

export function useViewSurfaceVisible(
  surfaceId: string | null | undefined
): boolean {
  return useContext(ViewContext).isVisible(surfaceId);
}

export function ViewSurfaceBoundary({
  surfaceId,
  children,
  fallback = null
}: {
  surfaceId: string;
  children: ReactNode;
  fallback?: ReactNode;
}) {
  return useViewSurfaceVisible(surfaceId) ? <>{children}</> : <>{fallback}</>;
}
