import * as Ariakit from '@ariakit/react';
import { getClassNames } from '@websolutespa/bom-core';
import { useContext } from 'react';
import styled from 'styled-components';
import { getVariantKey } from '../../variants';
import { getCssResponsive } from '../utils';
import { ModalDialogContext, ModalDialogProvider, ModalForceMountProvider } from './modal-dialog.context';
import { ModalContext } from './modal.context';
import { IModalVariants, modalVariants } from './modal.variants';

const StyledModalPortal = styled(Ariakit.Portal) <ModalPortalProps>`
  ${props => getVariantKey('portal', props.variant, props.variants)}
  ${props => getCssResponsive(props)}
`;

export type ModalPortalExtraProps = {
  open?: boolean;
  defaultOpen?: boolean;
  onOpenChange?: (open: boolean) => void;
  modal?: boolean;
};

export type ModalPortalProps = {
  open?: boolean;
  defaultOpen?: boolean;
  onOpenChange?: (open: boolean) => void;
  modal?: boolean;
} & {
  forceMount?: boolean;
  container?: HTMLElement | null;
  children?: React.ReactNode;
} & {
  className?: string;
  variant?: keyof typeof modalVariants | (string & {});
  variants?: IModalVariants;
};

export function ModalPortal({
  forceMount = false,
  container,
  children,
  className,
  variant,
  variants,
  //
  ...props
}: ModalPortalProps) {
  const store_ = Ariakit.useDialogStore({
    open: props.open,
    defaultOpen: props.defaultOpen,
    setOpen: props.onOpenChange,
  });
  const modal_ = props.modal ?? true;
  const contextValue = { store: store_, modal: modal_ };
  const context = useContext(ModalDialogContext);
  const { store } = context ? context : contextValue;
  const portalContext = useContext(Ariakit.PortalContext);
  const mounted = Ariakit.useStoreState(store, (state) => forceMount || state.mounted);
  const classNames = getClassNames('modal__portal', className);
  const variantContext = useContext(ModalContext);
  if (!mounted) {
    return null;
  }
  return context ? (
    <Ariakit.PortalContext.Provider value={container ?? portalContext}>
      <ModalForceMountProvider value={forceMount}>
        <StyledModalPortal
          className={classNames}
          variant={variant || variantContext.variant}
          variants={variants || variantContext.variants}
        >{children}</StyledModalPortal>
      </ModalForceMountProvider>
    </Ariakit.PortalContext.Provider>
  ) : (
    <ModalDialogProvider value={contextValue}>
      <Ariakit.PortalContext.Provider value={container ?? portalContext}>
        <ModalForceMountProvider value={forceMount}>
          <StyledModalPortal
            className={classNames}
            variant={variant || variantContext.variant}
            variants={variants || variantContext.variants}
          >{children}</StyledModalPortal>
        </ModalForceMountProvider>
      </Ariakit.PortalContext.Provider>
    </ModalDialogProvider>
  );
}
