import * as ModalPrimitive from '@radix-ui/react-dialog'
import { cva, type VariantProps } from 'class-variance-authority'
import type React from 'react'
import { SvgDelete1 } from '@chainlink/blocks-icons'
import { cn } from '../../utils'
import { Typography } from '../Typography'

/**
 * Root state container for a modal dialog. Manages open/closed state.
 * Compose with ModalTrigger and ModalContent.
 */
const Modal = ModalPrimitive.Root
Modal.displayName = 'Modal'

/** Element that opens the modal when interacted with. Use `asChild` to make any element the trigger. */
const ModalTrigger = ModalPrimitive.Trigger
ModalTrigger.displayName = 'ModalTrigger'

/** Portal that renders ModalContent outside the DOM tree. Used internally by ModalContent. */
const ModalPortal = ModalPrimitive.Portal
ModalPortal.displayName = 'ModalPortal'

/** Primitive close control. Use `asChild` to make any element close the modal. For a styled close button, use ModalCloseButton. */
const ModalClose = ModalPrimitive.Close
ModalClose.displayName = 'ModalClose'

type ModalCloseButtonProps = React.ComponentPropsWithoutRef<
  typeof ModalPrimitive.Close
> & {
  ref?: React.Ref<React.ElementRef<typeof ModalPrimitive.Close>>
}

/**
 * Styled circular close button (X icon) for use inside ModalContent. Already
 * rendered automatically by ModalContent unless `showCloseButton={false}`.
 * Use this manually when you need a close button in a custom layout.
 */
const ModalCloseButton = ({
  className,
  children,
  asChild,
  ref,
  ...props
}: ModalCloseButtonProps) => (
  <ModalPrimitive.Close
    ref={ref}
    asChild={asChild}
    className={cn(
      'absolute right-5 top-5 flex h-8 w-8 items-center justify-center rounded-full border border-solid border-border ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none md:right-8 md:top-8 md:h-10 md:w-10',
      className,
    )}
    aria-label="Close modal"
    {...props}
  >
    {asChild ? (
      children
    ) : (
      <>
        {children || (
          <SvgDelete1 color="muted" className="h-3 w-3 md:h-4 md:w-4" />
        )}
        <span className="sr-only">Close</span>
      </>
    )}
  </ModalPrimitive.Close>
)
ModalCloseButton.displayName = 'ModalCloseButton'

type ModalOverlayProps = React.ComponentPropsWithoutRef<
  typeof ModalPrimitive.Overlay
> & {
  ref?: React.Ref<React.ElementRef<typeof ModalPrimitive.Overlay>>
}

const ModalOverlay = ({ className, ref, ...props }: ModalOverlayProps) => (
  <ModalPrimitive.Overlay
    ref={ref}
    className={cn(
      'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
      className,
    )}
    {...props}
  />
)
ModalOverlay.displayName = 'ModalOverlay'

const modalContentVariants = cva(
  'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-0 border bg-background p-0 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
  {
    variants: {
      size: {
        default: 'max-w-3xl',
        sm: 'max-w-xl',
        lg: 'max-w-5xl',
      },
    },
    defaultVariants: {
      size: 'default',
    },
  },
)

type ModalContentProps = React.ComponentPropsWithoutRef<
  typeof ModalPrimitive.Content
> &
  VariantProps<typeof modalContentVariants> & {
    /** Controls the maximum width of the modal panel. Defaults to `default` (max-w-3xl). */
    size?: 'default' | 'sm' | 'lg'
    /** When false, hides the default ModalCloseButton. Use when you need a custom close layout. Defaults to true. */
    showCloseButton?: boolean
    /** Additional className for the overlay (backdrop). */
    overlayClassName?: string
    ref?: React.Ref<React.ElementRef<typeof ModalPrimitive.Content>>
  }

/**
 * Main dialog panel. Renders inside a portal with a backdrop overlay.
 * Includes a close button by default. Compose with ModalHeader, ModalBody,
 * and ModalFooter.
 */
const ModalContent = ({
  className,
  overlayClassName,
  children,
  size,
  showCloseButton = true,
  ref,
  ...props
}: ModalContentProps) => (
  <ModalPortal>
    <ModalOverlay className={overlayClassName} />
    <ModalPrimitive.Content
      ref={ref}
      className={cn(modalContentVariants({ size }), className)}
      aria-modal="true"
      role="modal"
      {...props}
    >
      {children}
      {showCloseButton && <ModalCloseButton aria-label="Close modal" />}
    </ModalPrimitive.Content>
  </ModalPortal>
)
ModalContent.displayName = 'ModalContent'

type ModalHeaderProps = React.HTMLAttributes<HTMLDivElement> & {
  /** When true, renders a bottom border between the header and the modal body. */
  showDivider?: boolean
}

/** Top section of the modal panel. Contains ModalTitle and optionally ModalDescription. */
const ModalHeader = ({
  className,
  showDivider = false,
  ...props
}: ModalHeaderProps) => (
  <div
    className={cn(
      'flex flex-col space-y-1.5 p-8 md:px-20 md:py-10',
      showDivider && 'border-b border-solid border-border',
      className,
    )}
    {...props}
  />
)
ModalHeader.displayName = 'ModalHeader'

type ModalFooterProps = React.HTMLAttributes<HTMLDivElement> & {
  /** When true, renders a top border between the modal body and the footer. */
  showDivider?: boolean
}

/** Bottom section of the modal panel. Lays out action buttons right-aligned in a row. */
const ModalFooter = ({
  className,
  showDivider = false,
  ...props
}: ModalFooterProps) => (
  <div
    className={cn(
      'flex flex-row justify-end gap-4 p-8 md:px-20 md:py-10',
      showDivider && 'border-t border-solid border-border',
      className,
    )}
    {...props}
  />
)
ModalFooter.displayName = 'ModalFooter'

type ModalTitleProps = React.ComponentPropsWithoutRef<
  typeof ModalPrimitive.Title
> & {
  ref?: React.Ref<React.ElementRef<typeof ModalPrimitive.Title>>
}

/** Accessible dialog title. Rendered as an `<h5>` via Typography. Required for screen reader announcements. */
const ModalTitle = ({ className, ref, ...props }: ModalTitleProps) => (
  <ModalPrimitive.Title ref={ref} className={cn(className)} asChild {...props}>
    <Typography variant="h5" color="foreground">
      {props.children}
    </Typography>
  </ModalPrimitive.Title>
)
ModalTitle.displayName = 'ModalTitle'

type ModalDescriptionProps = React.ComponentPropsWithoutRef<
  typeof ModalPrimitive.Description
> & {
  ref?: React.Ref<React.ElementRef<typeof ModalPrimitive.Description>>
}

/** Optional accessible description below the modal title. Announced by screen readers when the dialog opens. */
const ModalDescription = ({
  className,
  ref,
  ...props
}: ModalDescriptionProps) => (
  <ModalPrimitive.Description
    ref={ref}
    className={cn('mt-2', className)}
    asChild
    {...props}
  >
    <Typography variant="body-s" color="muted-more" asChild>
      <div>{props.children}</div>
    </Typography>
  </ModalPrimitive.Description>
)
ModalDescription.displayName = 'ModalDescription'

/** Scrollable content area between ModalHeader and ModalFooter. */
const ModalBody = ({
  className,
  ...props
}: React.HTMLAttributes<HTMLDivElement>) => (
  <div className={cn('p-8 md:px-20 md:py-10', className)} {...props} />
)
ModalBody.displayName = 'ModalBody'

export {
  Modal,
  ModalPortal,
  ModalOverlay,
  ModalClose,
  ModalCloseButton,
  ModalTrigger,
  ModalContent,
  ModalHeader,
  ModalFooter,
  ModalTitle,
  ModalDescription,
  ModalBody,
}
