import type { ReactNode, RefAttributes } from 'react';
import { cva, cx, VariantProps } from 'class-variance-authority';
import * as DialogPrimitive from '@radix-ui/react-dialog';

import { Button } from '../button';
import { Icon } from '../iconography';
import type { DialogFuncProps } from './types';
import './dialog.css';

const IconMap = {
  error: Icon.Error,
  info: Icon.Info,
  warning: Icon.Warning,
};

type DialogContentStylesProps = VariantProps<typeof dialogContentStyles>;
const dialogContentStyles = cva('c-dialog', {
  variants: {
    withIcon: {
      true: 'c-dialog-with-icon',
    },
  },
});

type DialogContentProps = DialogContentStylesProps & {
  children: ReactNode;
} & Pick<
    DialogFuncProps,
    'onEscapeKeyDown' | 'onInteractOutside' | 'onPointerDownOutside' | 'closable' | 'type' | 'className'
  > &
  DialogPrimitive.DialogContentProps &
  Pick<DialogPrimitive.PortalProps, 'container'>;

function DialogContent({ children, closable = true, type, className, container, ...delegated }: DialogContentProps) {
  const withIcon = typeof type !== 'undefined';

  const IconComponent = type && IconMap[type];

  return (
    <DialogPrimitive.Portal container={container}>
      <DialogPrimitive.Overlay className="c-dialog-overlay" />
      <DialogPrimitive.Content className={dialogContentStyles({ withIcon, class: className })} {...delegated}>
        {IconComponent && (
          <div className="c-dialog-icon-wrapper">
            <IconComponent className="c-dialog-icon" width={34} height={34} />
          </div>
        )}
        {closable && (
          <DialogClose asChild>
            <Button className="c-dialog-close-button">
              <Icon.Cancel color="density" aria-label="Close" height={16} width={16} />
            </Button>
          </DialogClose>
        )}
        <div>{children}</div>
      </DialogPrimitive.Content>
    </DialogPrimitive.Portal>
  );
}

type DialogTitleProps = JSX.IntrinsicAttributes & DialogPrimitive.DialogTitleProps & RefAttributes<HTMLHeadingElement>;

function DialogTitle({ className, ...delegated }: DialogTitleProps) {
  return <DialogPrimitive.Title className={cx('c-dialog-title', className)} {...delegated} />;
}

type DialogDescriptionProps = JSX.IntrinsicAttributes &
  DialogPrimitive.DialogDescriptionProps &
  RefAttributes<HTMLParagraphElement>;

function DialogDescription(delegated: DialogDescriptionProps) {
  return <DialogPrimitive.Description className="c-dialog-description" {...delegated} />;
}

const DialogTrigger = DialogPrimitive.Trigger;

const DialogClose = DialogPrimitive.Close;

export const DialogRoot = DialogPrimitive.Root;

type DialogBaseProps = React.ComponentProps<typeof DialogRoot> & {
  children: ReactNode;
};

export function DialogBase({ children, ...delegated }: DialogBaseProps) {
  return <DialogRoot {...delegated}>{children}</DialogRoot>;
}

DialogBase.Title = DialogTitle;
DialogBase.Trigger = DialogTrigger;
DialogBase.Description = DialogDescription;
DialogBase.Content = DialogContent;
DialogBase.Overlay = DialogPrimitive.Overlay;
DialogBase.Close = DialogPrimitive.Close;
