import {
  circleCheck,
  circleExclamation,
  circleInfo,
  cross,
  triangleExclamation,
} from "@simplybusiness/icons";
import classNames from "classnames/dedupe";
import type { ReactNode } from "react";
import { toast as sonnerToast } from "sonner";
import { Icon } from "../Icon";
import { toastState } from "./state";
import type { ToastOptions, ToastVariant } from "./types";
import "./Toast.css";

const variantIcons: Record<ToastVariant, typeof circleInfo> = {
  info: circleInfo,
  success: circleCheck,
  warning: triangleExclamation,
  error: circleExclamation,
};

const variantColors: Record<ToastVariant, string> = {
  info: "var(--color-info)",
  success: "var(--color-valid)",
  warning: "var(--color-warning)",
  error: "var(--color-error)",
};

const ToastIcon = ({ variant }: { variant: ToastVariant }) => (
  <span className="mobius-toast__icon">
    <Icon icon={variantIcons[variant]} color={variantColors[variant]} />
  </span>
);

const CloseIcon = () => (
  <span className="mobius-toast__close-icon">
    <Icon icon={cross} />
  </span>
);

type ToastContentProps = {
  toastId: string | number;
  variant: ToastVariant;
  title?: string;
  description?: ReactNode;
  action?: ToastOptions["action"];
  cancel?: ToastOptions["cancel"];
  showCloseButton?: boolean;
};

const ToastContent = ({
  toastId,
  variant,
  title,
  description,
  action,
  cancel,
  showCloseButton = toastState.showCloseButton,
}: ToastContentProps) => (
  <div className={classNames("mobius", "mobius-toast", `--${variant}`)}>
    <ToastIcon variant={variant} />
    <div className="mobius-toast__body">
      <div className="mobius-toast__content">
        {title && <div className="mobius-toast__title">{title}</div>}
        {description && (
          <div className="mobius-toast__description">{description}</div>
        )}
      </div>
      {(action || cancel) && (
        <div className="mobius-toast__actions">
          {cancel && (
            <button
              type="button"
              className="mobius-toast__cancel"
              onClick={() => {
                cancel.onClick?.();
                sonnerToast.dismiss(toastId);
              }}
            >
              {cancel.label}
            </button>
          )}
          {action && (
            <button
              type="button"
              className="mobius-toast__action"
              onClick={() => {
                action.onClick();
                sonnerToast.dismiss(toastId);
              }}
            >
              {action.label}
            </button>
          )}
        </div>
      )}
    </div>
    {showCloseButton && (
      <button
        type="button"
        className="mobius-toast__close"
        onClick={() => sonnerToast.dismiss(toastId)}
        aria-label="Close"
      >
        <CloseIcon />
      </button>
    )}
  </div>
);

const createCustomToast = (
  message: string,
  variant: ToastVariant,
  options?: ToastOptions,
) =>
  sonnerToast.custom(
    id => (
      <ToastContent
        toastId={id}
        variant={variant}
        title={options?.title}
        description={options?.description ?? message}
        action={options?.action}
        cancel={options?.cancel}
        showCloseButton={options?.showCloseButton}
      />
    ),
    {
      duration: options?.duration,
      onDismiss: options?.onDismiss,
      onAutoClose: options?.onAutoClose,
    },
  );

export const toast = {
  /** Show an info toast */
  info: (message: string, options?: ToastOptions) =>
    createCustomToast(message, "info", options),

  /** Show a success toast */
  success: (message: string, options?: ToastOptions) =>
    createCustomToast(message, "success", options),

  /** Show a warning toast */
  warning: (message: string, options?: ToastOptions) =>
    createCustomToast(message, "warning", options),

  /** Show an error toast */
  error: (message: string, options?: ToastOptions) =>
    createCustomToast(message, "error", options),

  /** Dismiss a specific toast by ID or all toasts */
  dismiss: (toastId?: string | number) => sonnerToast.dismiss(toastId),
};
