import React from 'react'
import * as ToastPrimitives from '@radix-ui/react-toast'
import { X } from 'lucide-react'
import tw, { TwStyle } from 'twin.macro'

const ToastProvider = ToastPrimitives.Provider
const ToastViewport = React.forwardRef<
  React.ElementRef<typeof ToastPrimitives.Viewport>,
  React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
>(({ ...props }, ref) => (
  <ToastPrimitives.Viewport
    ref={ref}
    css={tw`
      fixed
      top-0
      z-[100]
      flex
      max-h-screen
      w-full
      flex-col-reverse
      p-4
      sm:top-auto
      sm:bottom-0
      sm:right-0
      sm:flex-col md:max-w-[420px]
    `}
    {...props}
  />
))
ToastViewport.displayName = ToastPrimitives.Viewport.displayName
const PRIMARY_STYLE = tw`
  data-[swipe=move]:transition-none
  grow
  relative
  pointer-events-auto
  flex
  w-full
  items-center
  justify-between
  space-x-4
  overflow-hidden
  rounded-md
  border
  p-6
  pr-8
  shadow-lg
  transition-all
  data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)]
  data-[swipe=cancel]:translate-x-0
  data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)]
  data-[state=open]:animate-in
  data-[state=closed]:animate-out
  data-[swipe=end]:animate-out
  data-[state=closed]:fade-out-80
  data-[state=open]:slide-in-from-top-full
  data-[state=open]:sm:slide-in-from-bottom-full
  mt-4
  data-[state=closed]:slide-out-to-right-full
  dark:border-slate-700
  last:mt-0 sm:last:mt-4
`

type ToastVariantType = 'default' | 'destructive'

const VARIANT_MAP = {
  default: tw`bg-white border-slate-200 dark:bg-slate-800 dark:border-slate-700`,
  destructive: tw`bg-red-600 text-white border-red-600 dark:border-red-600`,
} satisfies Record<ToastVariantType, TwStyle>

interface ToastVariants
  extends React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> {
  variant?: ToastVariantType
}

const Toast = React.forwardRef<
  React.ElementRef<typeof ToastPrimitives.Root>,
  ToastVariants
>(({ variant = 'default', ...props }, ref) => (
  <ToastPrimitives.Root
    ref={ref}
    css={[PRIMARY_STYLE, VARIANT_MAP[variant]]}
    className="group"
    {...props}
  />
))
Toast.displayName = ToastPrimitives.Root.displayName

const ToastAction = React.forwardRef<
  React.ElementRef<typeof ToastPrimitives.Action>,
  React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
>(({ ...props }, ref) => (
  <ToastPrimitives.Action
    ref={ref}
    css={tw`
      inline-flex
      h-8
      shrink-0
      items-center
      justify-center
      rounded-md
      border
      border-slate-200
      bg-transparent
      px-3
      text-sm
      font-medium
      transition-colors
      hover:bg-slate-100
      focus:outline-none
      focus:ring-2
      focus:ring-slate-400
      focus:ring-offset-2
      disabled:pointer-events-none
      disabled:opacity-50
      group-[.destructive]:border-red-100
      group-[.destructive]:hover:border-slate-50
      group-[.destructive]:hover:bg-red-100
      group-[.destructive]:hover:text-red-600
      group-[.destructive]:focus:ring-red-400
      group-[.destructive]:focus:ring-offset-red-600
      dark:border-slate-700
      dark:text-slate-100
      dark:hover:bg-slate-700
      dark:hover:text-slate-100
      dark:focus:ring-slate-400
      dark:focus:ring-offset-slate-900
      dark:data-[state=open]:bg-slate-800
    `}
    {...props}
  />
))
ToastAction.displayName = ToastPrimitives.Action.displayName

const ToastClose = React.forwardRef<
  React.ElementRef<typeof ToastPrimitives.Close>,
  React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
>(({ ...props }, ref) => (
  <ToastPrimitives.Close
    ref={ref}
    css={tw`
      absolute
      top-2
      right-2
      rounded-md
      p-1
      text-slate-500
      opacity-0
      transition-opacity
      hover:text-slate-900
      focus:opacity-100
      focus:outline-none
      focus:ring-2
      group-hover:opacity-100
      group-[.destructive]:text-red-300
      group-[.destructive]:hover:text-red-50
      group-[.destructive]:focus:ring-red-400
      group-[.destructive]:focus:ring-offset-red-600
      dark:hover:text-slate-50
    `}
    toast-close=""
    {...props}
  >
    <X tw="h-4 w-4" />
  </ToastPrimitives.Close>
))
ToastClose.displayName = ToastPrimitives.Close.displayName

const ToastTitle = React.forwardRef<
  React.ElementRef<typeof ToastPrimitives.Title>,
  React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
>(({ ...props }, ref) => (
  <ToastPrimitives.Title ref={ref} tw="text-sm font-semibold" {...props} />
))
ToastTitle.displayName = ToastPrimitives.Title.displayName

const ToastDescription = React.forwardRef<
  React.ElementRef<typeof ToastPrimitives.Description>,
  React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
>(({ ...props }, ref) => (
  <ToastPrimitives.Description ref={ref} tw="text-sm opacity-90" {...props} />
))
ToastDescription.displayName = ToastPrimitives.Description.displayName

type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>

type ToastActionElement = React.ReactElement<typeof ToastAction>

const _ToastProvider = ToastProvider
export {
  _ToastProvider as ToastProvider,
  ToastViewport,
  Toast,
  ToastTitle,
  ToastDescription,
  ToastClose,
  ToastAction,
  VARIANT_MAP as TOAST_VARIANT_MAP,
}
export type { ToastProps, ToastActionElement, ToastVariantType, ToastVariants }
