import { getDocument, getWindow } from '@zag-js/dom-query';
import { trackSplit, track, type Component, type Tracked } from 'ripple';
import { runIfFn } from '../../utils/run-if-fn';
import {
  EnvironmentContext,
  type RootNode,
  type UseEnvironmentContext,
} from './use-environment-context';
import type { MaybeTracked } from '../../types';

export interface EnvironmentProviderProps {
  children?: Component;
  value?: Tracked<RootNode> | RootNode | (() => Tracked<RootNode> | RootNode);
}

export component EnvironmentProvider(props: MaybeTracked<EnvironmentProviderProps>) {
  const [children, value] = trackSplit(props, ['children', 'value']);
  let spanRef = track<HTMLSpanElement | null>(null);

  const getRootNode = () => runIfFn(@value) ?? @spanRef?.getRootNode() ?? document;

  const environment = track(
    () => ({
      getRootNode,
      getDocument: () => getDocument(getRootNode() as Document),
      getWindow: () => getWindow(getRootNode() as Document),
    }),
  );

  EnvironmentContext.set(environment as Tracked<UseEnvironmentContext>);

  <@children />
  if (!@value) {
    <span
      hidden
      {ref (el: HTMLSpanElement) => {
        @spanRef = el;
        return () => {
          @spanRef = null;
        };
      }}
    />
  }
}
