'use client'

import { createCheckbox } from '@gluestack-ui/checkbox'
import { IPrimitiveIcon, PrimitiveIcon, UIIcon } from '@gluestack-ui/icon'
import type { VariantProps } from '@gluestack-ui/nativewind-utils'
import { tva } from '@gluestack-ui/nativewind-utils/tva'
import { useStyleContext, withStyleContext } from '@gluestack-ui/nativewind-utils/withStyleContext'
import { cssInterop } from 'nativewind'
import { Check } from 'phosphor-react-native'
import React, { FC, ReactNode } from 'react'
import { Pressable, View } from 'react-native'
import type { ViewProps } from 'react-native'

import Text from '../text'

const IndicatorWrapper = React.forwardRef<React.ComponentRef<typeof View>, ViewProps & { states?: any }>(
  function IndicatorWrapper({ ...props }, ref) {
    const { size: parentSize } = useStyleContext(SCOPE)

    return (
      <View className="relative">
        {props.states.active && (
          <View
            className={checkboxOnTapStyle({
              parentVariants: {
                size: parentSize,
              },
            })}
          />
        )}
        <View {...props} ref={ref} />
      </View>
    )
  },
)

const IconWrapper = React.forwardRef<
  React.ComponentRef<typeof PrimitiveIcon>,
  IPrimitiveIcon & { dataSet?: Record<string, string> }
>(function IconWrapper({ ...props }, ref) {
  return <UIIcon {...props} ref={ref} />
})

const SCOPE = 'CHECKBOX'
const UICheckbox = createCheckbox({
  Root: withStyleContext(Pressable, SCOPE),
  Group: View,
  Icon: IconWrapper,
  Label: View,
  Indicator: IndicatorWrapper,
})

cssInterop(PrimitiveIcon, {
  className: {
    target: 'style',
    nativeStyleToProp: {
      height: true,
      width: true,
      fill: true,
      color: 'classNameColor',
      stroke: true,
    },
  },
})

const checkboxStyle = tva({
  base: 'group/checkbox flex-row items-center justify-start',
  variants: {
    size: {
      lg: 'gap-2',
      md: 'gap-2',
    },
  },
})

const checkboxIndicatorStyle = tva({
  base: '-z-5 relative items-center justify-center rounded-[var(--checkbox-radius)] border-selector-border bg-selector-background data-[checked=true]:border-selector-border-active data-[checked=true]:bg-selector-accent-true data-[invalid=true]:border-destructive-border data-[active=true]:data-[checked=true]:bg-selector-accent-onTap data-[active=true]:data-[checked=true]:border-selector-border-active data-[active=true]:!border-selector-border-onTap data-[disabled=true]:border-disabled-border data-[disabled=true]:bg-disabled',
  parentVariants: {
    size: {
      lg: 'size-[var(--lg-checkbox-size)] border-[length:var(--lg-checkbox-border-size)]',
      md: 'size-[var(--checkbox-size)] border-[length:var(--checkbox-border-size)]',
    },
  },
})

const checkboxOnTapStyle = tva({
  base: 'absolute rounded-full bg-selector-accent-onTap opacity-5',
  parentVariants: {
    size: {
      lg: '-left-[calc(var(--lg-radio-onTap-size)/2-var(--lg-radio-size)/2)] -top-[calc(var(--lg-radio-onTap-size)/2-var(--lg-radio-size)/2)] size-[var(--lg-radio-onTap-size)]',
      md: '-left-[calc(var(--radio-onTap-size)/2-var(--radio-size)/2)] -top-[calc(var(--radio-onTap-size)/2-var(--radio-size)/2)] size-[var(--radio-onTap-size)]',
    },
  },
})

const checkboxIconStyle = tva({
  base: 'fill-selector-foreground data-[disabled=true]:fill-disabled-foreground',
  parentVariants: {
    size: {
      lg: 'size-[var(--lg-checkbox-icon-size)]',
      md: 'size-[var(--checkbox-icon-size)]',
    },
  },
})

const CheckboxGroup = UICheckbox.Group

type ICheckboxProps = React.ComponentPropsWithoutRef<typeof UICheckbox> & VariantProps<typeof checkboxStyle>

const CheckboxWrapper = React.forwardRef<React.ComponentRef<typeof UICheckbox>, ICheckboxProps>(function Checkbox(
  { className, size = 'md', ...props },
  ref,
) {
  return (
    <UICheckbox
      className={checkboxStyle({
        class: className,
        size,
      })}
      {...props}
      context={{
        size,
        isDisabled: props.isDisabled,
      }}
      ref={ref}
    />
  )
})

type ICheckboxIndicatorProps = React.ComponentPropsWithoutRef<typeof UICheckbox.Indicator> &
  VariantProps<typeof checkboxIndicatorStyle>

const CheckboxIndicator = React.forwardRef<React.ComponentRef<typeof UICheckbox.Indicator>, ICheckboxIndicatorProps>(
  function CheckboxIndicator({ className, ...props }, ref) {
    const { size: parentSize } = useStyleContext(SCOPE)
    return (
      <UICheckbox.Indicator
        className={checkboxIndicatorStyle({
          parentVariants: {
            size: parentSize,
          },
          class: className,
        })}
        {...props}
        ref={ref}
      />
    )
  },
)

type ICheckboxLabelProps = React.ComponentPropsWithoutRef<typeof UICheckbox.Label>
const CheckboxLabel = React.forwardRef<React.ComponentRef<typeof UICheckbox.Label>, ICheckboxLabelProps>(
  function CheckboxLabel({ className, children, ...props }, ref) {
    return (
      <UICheckbox.Label ref={ref} {...props}>
        {typeof children === 'string' ? (
          <Text variant="p" className="group-data-[invalid=true]/checkbox:text-destructive-background">
            {children}
          </Text>
        ) : (
          children
        )}
      </UICheckbox.Label>
    )
  },
)

type ICheckboxIconProps = React.ComponentPropsWithoutRef<typeof UICheckbox.Icon> &
  VariantProps<typeof checkboxIconStyle>

const CheckboxIcon = React.forwardRef<React.ComponentRef<typeof UICheckbox.Icon>, ICheckboxIconProps>(
  function CheckboxIcon({ className, size, ...props }, ref) {
    const { size: parentSize, isDisabled } = useStyleContext(SCOPE)

    if (typeof size === 'number') {
      return (
        <UICheckbox.Icon
          ref={ref}
          {...props}
          className={checkboxIconStyle({ class: className })}
          size={size}
          data-disabled={isDisabled ? 'true' : 'false'}
        />
      )
    } else if ((props.height !== undefined || props.width !== undefined) && size === undefined) {
      return (
        <UICheckbox.Icon
          ref={ref}
          {...props}
          className={checkboxIconStyle({ class: className })}
          data-disabled={isDisabled ? 'true' : 'false'}
        />
      )
    }

    return (
      <UICheckbox.Icon
        className={checkboxIconStyle({
          parentVariants: {
            size: parentSize,
          },
          class: className,
          size,
        })}
        {...props}
        ref={ref}
        dataSet={{
          disabled: isDisabled ? 'true' : 'false',
        }}
      />
    )
  },
)

const Checkbox: FC<ICheckboxProps & { label?: ReactNode }> = ({ label, ...props }) => {
  return (
    <CheckboxWrapper {...props}>
      <CheckboxIndicator>
        <CheckboxIcon as={Check} />
      </CheckboxIndicator>
      {label && <CheckboxLabel>{label}</CheckboxLabel>}
    </CheckboxWrapper>
  )
}

Checkbox.displayName = 'Checkbox'
CheckboxWrapper.displayName = 'CheckboxWrapper'
CheckboxIndicator.displayName = 'CheckboxIndicator'
CheckboxLabel.displayName = 'CheckboxLabel'
CheckboxIcon.displayName = 'CheckboxIcon'

export { Checkbox, CheckboxWrapper, CheckboxIndicator, CheckboxLabel, CheckboxIcon, CheckboxGroup }
