import * as Ariakit from '@ariakit/react';
import { getClassNames } from '@websolutespa/bom-core';
import { forwardRef, useContext, useEffect, useState } from 'react';
import styled from 'styled-components';
import { getVariantKey } from '../../variants';
import { Role } from '../role/role';
import { UIStyledComponentProps } from '../types';
import { getCssResponsive } from '../utils';
import { ModalDialogContext, ModalForceMountContext } from './modal-dialog.context';
import { ModalContext } from './modal.context';
import { IModalVariants, modalVariants } from './modal.variants';

const StyledBackdrop = styled(Ariakit.DisclosureContent) <ModalBackdropProps>`
  ${props => getVariantKey('backdrop', props.variant, props.variants)}
  ${props => getCssResponsive(props)}
`;

export type ModalBackdropProps = UIStyledComponentProps<{
  className?: string;
  variant?: keyof typeof modalVariants | (string & {});
  variants?: IModalVariants;
  asChild?: boolean;
  forceMount?: boolean;
}>;

export const ModalBackdrop = forwardRef<HTMLDivElement, ModalBackdropProps>(
  function ModalBackdrop({
    asChild,
    forceMount,
    className,
    variant,
    variants,
    ...props
  }, ref) {
    const { store } = useContext(ModalDialogContext)!;
    const forceMountContext = useContext(ModalForceMountContext);
    forceMount = forceMount ?? forceMountContext;
    const mounted = Ariakit.useStoreState(store, (state) => forceMount || state.mounted);
    const open = Ariakit.useStoreState(store, 'open');
    const [state, setState] = useState('closed');
    // Sets the state on the next animation frame so that the transition can be
    // triggered.
    useEffect(() => {
      const raf = requestAnimationFrame(() => {
        setState(open ? 'open' : 'closed');
      });
      return () => cancelAnimationFrame(raf);
    }, [open]);
    const disclosure = Ariakit.useDisclosureStore({
      open,
      setOpen: store.setOpen,
    });
    const classNames = getClassNames('modal__backdrop', className);
    const context = useContext(ModalContext);
    if (!mounted) {
      return null;
    }
    return (
      <StyledBackdrop
        {...props}
        className={classNames}
        variant={variant || context.variant}
        variants={variants || context.variants}
        ref={ref}
        store={disclosure}
        data-state={state}
        render={asChild ? <Role /> : undefined}
      />
    );
  });
