import * as React from 'react'
import { motion } from 'framer-motion'
import * as DialogPrimitive from '@radix-ui/react-dialog'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'
import { MOTION_FADE, MOTION_SLIDE_UP } from '@/lib/motion'
import { CloseLine } from './icons-inline'
import { getThemeFromDocument } from './theme-from-document'

const Dialog = DialogPrimitive.Root
const DialogTrigger = DialogPrimitive.Trigger
const DialogPortal = DialogPrimitive.Portal
const DialogClose = DialogPrimitive.Close

const DialogOverlay = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Overlay>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
>(({ className, ...props }, ref) => (
  <DialogPrimitive.Overlay ref={ref} asChild {...props}>
    <motion.div
      className={cn('fixed inset-0 z-50 bg-bg-mask/60', className)}
      {...MOTION_FADE}
    />
  </DialogPrimitive.Overlay>
))
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName

const contentVariants = cva(
  'font-sans fixed left-1/2 top-1/2 z-50 w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 rounded-xl border border-border bg-bg-base text-text shadow-lg p-6 outline-none',
  {
    variants: {
      size: {
        sm: 'max-w-sm',
        default: 'max-w-lg',
        lg: 'max-w-2xl',
        xl: 'max-w-4xl',
      },
    },
    defaultVariants: { size: 'default' },
  },
)

export interface DialogContentProps
  extends React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>,
    VariantProps<typeof contentVariants> {
  size?: 'sm' | 'default' | 'lg' | 'xl'
  /** Hide the built-in top-right close button. */
  hideCloseButton?: boolean
  /** When provided (e.g. from ThemeStyleProvider), used for portal wrapper */
  dataStyle?: string
  dataTheme?: string
}

const DialogContent = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Content>,
  DialogContentProps
>(
  (
    {
      className,
      children,
      size = 'default',
      hideCloseButton = false,
      dataStyle,
      dataTheme,
      ...props
    },
    ref,
  ) => {
    const fromDoc = getThemeFromDocument()
    const dataProps =
      dataStyle !== undefined
        ? { 'data-style': dataStyle, 'data-theme': dataTheme ?? fromDoc['data-theme'] ?? '' }
        : fromDoc
    return (
      <DialogPortal>
        <div style={{ display: 'contents' }} {...dataProps}>
          <DialogOverlay />
          <DialogPrimitive.Content ref={ref} asChild {...props}>
            <motion.div
              className={cn(contentVariants({ size }), className)}
              {...MOTION_SLIDE_UP}
            >
              {children}
              {!hideCloseButton && (
                <DialogPrimitive.Close
                  className={cn(
                    'absolute right-4 top-4 inline-flex size-7 items-center justify-center rounded-md text-text-tertiary opacity-70 transition-colors',
                    'hover:bg-fill-secondary hover:text-text hover:opacity-100',
                    'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-border',
                    'disabled:pointer-events-none',
                  )}
                >
                  <CloseLine className="size-4" />
                  <span className="sr-only">Close</span>
                </DialogPrimitive.Close>
              )}
            </motion.div>
          </DialogPrimitive.Content>
        </div>
      </DialogPortal>
    )
  },
)
DialogContent.displayName = DialogPrimitive.Content.displayName

const DialogHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
  ({ className, ...props }, ref) => (
    <div ref={ref} className={cn('flex flex-col gap-2 text-left', className)} {...props} />
  ),
)
DialogHeader.displayName = 'DialogHeader'

const DialogFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
  ({ className, ...props }, ref) => (
    <div
      ref={ref}
      className={cn('mt-6 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className)}
      {...props}
    />
  ),
)
DialogFooter.displayName = 'DialogFooter'

const DialogTitle = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Title>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
>(({ className, ...props }, ref) => (
  <DialogPrimitive.Title
    ref={ref}
    className={cn('font-sans text-base font-medium leading-6 text-text', className)}
    {...props}
  />
))
DialogTitle.displayName = DialogPrimitive.Title.displayName

const DialogDescription = React.forwardRef<
  React.ElementRef<typeof DialogPrimitive.Description>,
  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
>(({ className, ...props }, ref) => (
  <DialogPrimitive.Description
    ref={ref}
    className={cn('text-sm leading-6 text-text-tertiary', className)}
    {...props}
  />
))
DialogDescription.displayName = DialogPrimitive.Description.displayName

export type DialogHeaderProps = React.HTMLAttributes<HTMLDivElement>
export type DialogFooterProps = React.HTMLAttributes<HTMLDivElement>

export {
  Dialog,
  DialogTrigger,
  DialogPortal,
  DialogOverlay,
  DialogClose,
  DialogContent,
  DialogHeader,
  DialogFooter,
  DialogTitle,
  DialogDescription,
  contentVariants as dialogContentVariants,
}
