'use client';
import React from 'react';
import { createModal as createDrawer } from '@gluestack-ui/modal';
import {
  Pressable,
  View,
  ScrollView,
  Dimensions,
  ViewStyle,
} from 'react-native';
import {
  Motion,
  AnimatePresence,
  createMotionAnimatedComponent,
  MotionComponentProps,
} from '@legendapp/motion';
import { tva } from '@gluestack-ui/nativewind-utils/tva';
import {
  withStyleContext,
  useStyleContext,
} from '@gluestack-ui/nativewind-utils/withStyleContext';
import { cssInterop } from 'nativewind';
import type { VariantProps } from '@gluestack-ui/nativewind-utils';

type IAnimatedPressableProps = React.ComponentProps<typeof Pressable> &
  MotionComponentProps<typeof Pressable, ViewStyle, unknown, unknown, unknown>;

const AnimatedPressable = createMotionAnimatedComponent(
  Pressable
) as React.ComponentType<IAnimatedPressableProps>;

const SCOPE = 'MODAL';
const screenWidth = Dimensions.get('window').width;
const screenHeight = Dimensions.get('window').height;
const sizes: { [key: string]: number } = {
  sm: 0.25,
  md: 0.5,
  lg: 0.75,
  full: 1,
};

type IMotionViewProps = React.ComponentProps<typeof View> &
  MotionComponentProps<typeof View, ViewStyle, unknown, unknown, unknown>;

const MotionView = Motion.View as React.ComponentType<IMotionViewProps>;

const UIDrawer = createDrawer({
  Root: withStyleContext(View, SCOPE),
  Backdrop: AnimatedPressable,
  Content: MotionView,
  Body: ScrollView,
  CloseButton: Pressable,
  Footer: View,
  Header: View,
  AnimatePresence: AnimatePresence,
});

cssInterop(AnimatedPressable, { className: 'style' });
cssInterop(MotionView, { className: 'style' });

const drawerStyle = tva({
  base: 'w-full h-full web:pointer-events-none relative',
  variants: {
    size: {
      sm: '',
      md: '',
      lg: '',
      full: '',
    },
    anchor: {
      left: 'items-start',
      right: 'items-end',
      top: 'justify-start',
      bottom: 'justify-end',
    },
  },
});

const drawerBackdropStyle = tva({
  base: 'absolute left-0 top-0 right-0 bottom-0 bg-background-dark web:cursor-default',
});

const drawerContentStyle = tva({
  base: 'bg-background-0 overflow-scroll border-outline-100 p-6 absolute',
  parentVariants: {
    size: {
      sm: 'w-1/4',
      md: 'w-1/2',
      lg: 'w-3/4',
      full: 'w-full',
    },
    anchor: {
      left: 'h-full border-r',
      right: 'h-full border-l',
      top: 'w-full border-b',
      bottom: 'w-full border-t',
    },
  },
  parentCompoundVariants: [
    {
      anchor: 'top',
      size: 'sm',
      class: 'h-1/4',
    },
    {
      anchor: 'top',
      size: 'md',
      class: 'h-1/2',
    },
    {
      anchor: 'top',
      size: 'lg',
      class: 'h-3/4',
    },
    {
      anchor: 'top',
      size: 'full',
      class: 'h-full',
    },
    {
      anchor: 'bottom',
      size: 'sm',
      class: 'h-1/4',
    },
    {
      anchor: 'bottom',
      size: 'md',
      class: 'h-1/2',
    },
    {
      anchor: 'bottom',
      size: 'lg',
      class: 'h-3/4',
    },
    {
      anchor: 'bottom',
      size: 'full',
      class: 'h-full',
    },
  ],
});

const drawerCloseButtonStyle = tva({
  base: 'z-10 rounded data-[focus-visible=true]:web:bg-background-100 web:outline-0 cursor-pointer',
});

const drawerHeaderStyle = tva({
  base: 'justify-between items-center flex-row',
});

const drawerBodyStyle = tva({
  base: 'mt-4 mb-6 shrink-0',
});

const drawerFooterStyle = tva({
  base: 'flex-row justify-end items-center',
});

type IDrawerProps = React.ComponentProps<typeof UIDrawer> &
  VariantProps<typeof drawerStyle> & { className?: string };

type IDrawerBackdropProps = React.ComponentProps<typeof UIDrawer.Backdrop> &
  VariantProps<typeof drawerBackdropStyle> & { className?: string };

type IDrawerContentProps = React.ComponentProps<typeof UIDrawer.Content> &
  VariantProps<typeof drawerContentStyle> & { className?: string };

type IDrawerHeaderProps = React.ComponentProps<typeof UIDrawer.Header> &
  VariantProps<typeof drawerHeaderStyle> & { className?: string };

type IDrawerBodyProps = React.ComponentProps<typeof UIDrawer.Body> &
  VariantProps<typeof drawerBodyStyle> & { className?: string };

type IDrawerFooterProps = React.ComponentProps<typeof UIDrawer.Footer> &
  VariantProps<typeof drawerFooterStyle> & { className?: string };

type IDrawerCloseButtonProps = React.ComponentProps<
  typeof UIDrawer.CloseButton
> &
  VariantProps<typeof drawerCloseButtonStyle> & { className?: string };

const Drawer = React.forwardRef<
  React.ComponentRef<typeof UIDrawer>,
  IDrawerProps
>(function Drawer({ className, size = 'sm', anchor = 'left', ...props }, ref) {
  return (
    <UIDrawer
      ref={ref}
      {...props}
      pointerEvents="box-none"
      className={drawerStyle({ size, anchor, class: className })}
      context={{ size, anchor }}
    />
  );
});

const DrawerBackdrop = React.forwardRef<
  React.ComponentRef<typeof UIDrawer.Backdrop>,
  IDrawerBackdropProps
>(function DrawerBackdrop({ className, ...props }, ref) {
  return (
    <UIDrawer.Backdrop
      ref={ref}
      initial={{
        opacity: 0,
      }}
      animate={{
        opacity: 0.5,
      }}
      exit={{
        opacity: 0,
      }}
      transition={{
        type: 'spring',
        damping: 18,
        stiffness: 250,
        opacity: {
          type: 'timing',
          duration: 250,
        },
      }}
      {...props}
      className={drawerBackdropStyle({
        class: className,
      })}
    />
  );
});

const DrawerContent = React.forwardRef<
  React.ComponentRef<typeof UIDrawer.Content>,
  IDrawerContentProps
>(function DrawerContent({ className, ...props }, ref) {
  const { size: parentSize, anchor: parentAnchor } = useStyleContext(SCOPE);

  const drawerHeight = screenHeight * (sizes[parentSize] || sizes.md);
  const drawerWidth = screenWidth * (sizes[parentSize] || sizes.md);

  const isHorizontal = parentAnchor === 'left' || parentAnchor === 'right';

  const initialObj = isHorizontal
    ? { x: parentAnchor === 'left' ? -drawerWidth : drawerWidth }
    : { y: parentAnchor === 'top' ? -drawerHeight : drawerHeight };

  const animateObj = isHorizontal ? { x: 0 } : { y: 0 };

  const exitObj = isHorizontal
    ? { x: parentAnchor === 'left' ? -drawerWidth : drawerWidth }
    : { y: parentAnchor === 'top' ? -drawerHeight : drawerHeight };

  const customClass = isHorizontal
    ? `top-0 ${parentAnchor === 'left' ? 'left-0' : 'right-0'}`
    : `left-0 ${parentAnchor === 'top' ? 'top-0' : 'bottom-0'}`;

  return (
    <UIDrawer.Content
      ref={ref}
      initial={initialObj}
      animate={animateObj}
      exit={exitObj}
      transition={{
        type: 'timing',
        duration: 300,
      }}
      {...props}
      className={drawerContentStyle({
        parentVariants: {
          size: parentSize,
          anchor: parentAnchor,
        },
        class: `${className} ${customClass}`,
      })}
      pointerEvents="auto"
    />
  );
});

const DrawerHeader = React.forwardRef<
  React.ComponentRef<typeof UIDrawer.Header>,
  IDrawerHeaderProps
>(function DrawerHeader({ className, ...props }, ref) {
  return (
    <UIDrawer.Header
      ref={ref}
      {...props}
      className={drawerHeaderStyle({
        class: className,
      })}
    />
  );
});

const DrawerBody = React.forwardRef<
  React.ComponentRef<typeof UIDrawer.Body>,
  IDrawerBodyProps
>(function DrawerBody({ className, ...props }, ref) {
  return (
    <UIDrawer.Body
      ref={ref}
      {...props}
      className={drawerBodyStyle({
        class: className,
      })}
    />
  );
});

const DrawerFooter = React.forwardRef<
  React.ComponentRef<typeof UIDrawer.Footer>,
  IDrawerFooterProps
>(function DrawerFooter({ className, ...props }, ref) {
  return (
    <UIDrawer.Footer
      ref={ref}
      {...props}
      className={drawerFooterStyle({
        class: className,
      })}
    />
  );
});

const DrawerCloseButton = React.forwardRef<
  React.ComponentRef<typeof UIDrawer.CloseButton>,
  IDrawerCloseButtonProps
>(function DrawerCloseButton({ className, ...props }, ref) {
  return (
    <UIDrawer.CloseButton
      ref={ref}
      {...props}
      className={drawerCloseButtonStyle({
        class: className,
      })}
    />
  );
});

Drawer.displayName = 'Drawer';
DrawerBackdrop.displayName = 'DrawerBackdrop';
DrawerContent.displayName = 'DrawerContent';
DrawerHeader.displayName = 'DrawerHeader';
DrawerBody.displayName = 'DrawerBody';
DrawerFooter.displayName = 'DrawerFooter';
DrawerCloseButton.displayName = 'DrawerCloseButton';

export {
  Drawer,
  DrawerBackdrop,
  DrawerContent,
  DrawerCloseButton,
  DrawerHeader,
  DrawerBody,
  DrawerFooter,
};
