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

const Sheet = SheetPrimitive.Root

const SheetTrigger = SheetPrimitive.Trigger

const defaultPortalPositionStyle = tw`fixed inset-0 z-50 flex`
type PortalPositionType = 'top' | 'bottom' | 'left' | 'right'
const portalPositionMap = {
  top: tw`items-start`,
  bottom: tw`items-end`,
  left: tw`justify-start`,
  right: tw`justify-end`,
} satisfies Record<PortalPositionType, TwStyle>

interface SheetPortalProps extends SheetPrimitive.DialogPortalProps {
  position?: PortalPositionType
}

function SheetPortal({
  position = 'right',
  children,
  ...props
}: SheetPortalProps) {
  return (
    <SheetPrimitive.Portal {...props}>
      <div css={[defaultPortalPositionStyle, portalPositionMap[position]]}>
        {children}
      </div>
    </SheetPrimitive.Portal>
  )
}
SheetPortal.displayName = SheetPrimitive.Portal.displayName

const SheetOverlay = React.forwardRef<
  React.ElementRef<typeof SheetPrimitive.Overlay>,
  React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
>(({ ...props }, ref) => (
  <SheetPrimitive.Overlay
    tw="data-[state=closed]:animate-out data-[state=open]:fade-in data-[state=closed]:fade-out fixed inset-0 z-50 bg-black/50 backdrop-blur-sm transition-all duration-100"
    {...props}
    ref={ref}
  />
))
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName

// const defaultSheetPositionStyle = tw`fixed z-50 scale-100 gap-4 bg-white p-6 opacity-100 dark:bg-slate-900`;

type positionStyleType = 'top' | 'bottom' | 'left' | 'right'
type sizeType = 'content' | 'default' | 'sm' | 'lg' | 'xl' | 'full'

const sheetVariants = (position: positionStyleType, size: sizeType) => [
  tw`fixed z-50 scale-100 gap-4 bg-white p-6 opacity-100 dark:bg-slate-900`,
  position === 'top' && tw`animate-in slide-in-from-top w-full duration-300`,
  position === 'bottom' &&
    tw`animate-in slide-in-from-bottom w-full duration-300`,
  position === 'left' && tw`animate-in slide-in-from-left h-full duration-300`,
  position === 'right' &&
    tw`animate-in slide-in-from-right h-full duration-300`,
  size === 'content' && tw`max-h-screen`,
  size === 'default' && tw`h-1/3`,
  size === 'sm' && tw`h-1/4`,
  size === 'lg' && tw`h-1/2`,
  size === 'xl' && tw`h-5/6`,
  size === 'full' && tw`h-screen`,
]

export interface DialogContentProps
  extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content> {
  position: positionStyleType
  size: sizeType
}

const SheetContent = React.forwardRef<
  React.ElementRef<typeof SheetPrimitive.Content>,
  DialogContentProps
>(({ position, size, children, ...props }, ref) => (
  <SheetPortal position={position}>
    <SheetOverlay />
    <SheetPrimitive.Content
      ref={ref}
      css={sheetVariants(position, size)}
      {...props}
    >
      {children}
      <SheetPrimitive.Close tw="absolute top-4 right-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-slate-100 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-900 dark:data-[state=open]:bg-slate-800">
        <X tw="h-4 w-4" />
        <span tw="sr-only">Close</span>
      </SheetPrimitive.Close>
    </SheetPrimitive.Content>
  </SheetPortal>
))
SheetContent.displayName = SheetPrimitive.Content.displayName

function SheetHeader({ ...props }: React.HTMLAttributes<HTMLDivElement>) {
  return (
    <div
      css={[tw`flex flex-col space-y-2 text-center sm:text-left`]}
      {...props}
    />
  )
}
SheetHeader.displayName = 'SheetHeader'

function SheetFooter({ ...props }: React.HTMLAttributes<HTMLDivElement>) {
  return (
    <div
      css={[tw`flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2`]}
      {...props}
    />
  )
}
SheetFooter.displayName = 'SheetFooter'

const SheetTitle = React.forwardRef<
  React.ElementRef<typeof SheetPrimitive.Title>,
  React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
>(({ ...props }, ref) => (
  <SheetPrimitive.Title
    ref={ref}
    css={[tw`text-lg font-semibold text-slate-900`, tw`dark:text-slate-50`]}
    {...props}
  />
))
SheetTitle.displayName = SheetPrimitive.Title.displayName

const SheetDescription = React.forwardRef<
  React.ElementRef<typeof SheetPrimitive.Description>,
  React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
>(({ ...props }, ref) => (
  <SheetPrimitive.Description
    ref={ref}
    css={[tw`text-sm text-slate-500`, tw`dark:text-slate-400`]}
    {...props}
  />
))
SheetDescription.displayName = SheetPrimitive.Description.displayName

const _Sheet = Sheet
export {
  _Sheet as Sheet,
  SheetTrigger,
  SheetContent,
  SheetHeader,
  SheetFooter,
  SheetTitle,
  SheetDescription,
  type PortalPositionType,
  portalPositionMap,
}
