import * as ToastPrimitive from "@radix-ui/react-toast";
import { forwardRef, type ComponentPropsWithoutRef, type ElementRef } from "react";

import { toastActionVariants, toastCloseVariants, toastVariants, toastViewportVariants } from "./toast.variants";
import { cn } from "../lib/cn";
import type { VariantProps } from "../lib/cva";
import { createDataAttributes, createSlot } from "../lib/contracts";
import { CloseIcon } from "../lib/icons";

export const ToastProvider = ToastPrimitive.Provider;

export const ToastViewport = forwardRef<
  ElementRef<typeof ToastPrimitive.Viewport>,
  ComponentPropsWithoutRef<typeof ToastPrimitive.Viewport>
>(function ToastViewport({ className, ...props }, ref) {
  return (
    <ToastPrimitive.Viewport
      {...props}
      {...createSlot("viewport")}
      className={cn(toastViewportVariants(), className)}
      ref={ref}
    />
  );
});

export type ToastProps = ComponentPropsWithoutRef<typeof ToastPrimitive.Root> &
  VariantProps<typeof toastVariants>;

export const Toast = forwardRef<
  ElementRef<typeof ToastPrimitive.Root>,
  ToastProps
>(function Toast({ className, variant, ...props }, ref) {
  return (
    <ToastPrimitive.Root
      {...props}
      {...createSlot("root")}
      {...createDataAttributes({ variant })}
      className={cn(toastVariants({ variant }), className)}
      ref={ref}
    />
  );
});

export const ToastTitle = forwardRef<
  ElementRef<typeof ToastPrimitive.Title>,
  ComponentPropsWithoutRef<typeof ToastPrimitive.Title>
>(function ToastTitle({ className, ...props }, ref) {
  return (
    <ToastPrimitive.Title
      {...props}
      {...createSlot("label")}
      className={cn("col-start-1 row-start-1 text-sm font-semibold", className)}
      ref={ref}
    />
  );
});

export const ToastDescription = forwardRef<
  ElementRef<typeof ToastPrimitive.Description>,
  ComponentPropsWithoutRef<typeof ToastPrimitive.Description>
>(function ToastDescription({ className, ...props }, ref) {
  return (
    <ToastPrimitive.Description
      {...props}
      {...createSlot("description")}
      className={cn("col-start-1 row-start-2 text-sm leading-6 text-[var(--color-muted-foreground)]", className)}
      ref={ref}
    />
  );
});

export const ToastAction = forwardRef<
  ElementRef<typeof ToastPrimitive.Action>,
  ComponentPropsWithoutRef<typeof ToastPrimitive.Action>
>(function ToastAction({ className, ...props }, ref) {
  return (
    <ToastPrimitive.Action
      {...props}
      {...createSlot("action")}
      className={cn(toastActionVariants(), className)}
      ref={ref}
    />
  );
});

export const ToastClose = forwardRef<
  ElementRef<typeof ToastPrimitive.Close>,
  ComponentPropsWithoutRef<typeof ToastPrimitive.Close>
>(function ToastClose({ children, className, ...props }, ref) {
  return (
    <ToastPrimitive.Close
      {...props}
      aria-label={props["aria-label"] ?? "Close notification"}
      {...createSlot("close")}
      className={cn(toastCloseVariants(), className)}
      ref={ref}
    >
      {children ?? (
        <CloseIcon className="size-4" />
      )}
    </ToastPrimitive.Close>
  );
});
