import React from 'react'
import { View, StyleSheet, Platform } from 'react-native'
import PropTypes from 'prop-types'
import { Box } from '../Box/Box'
import { Button } from '../Button/Button'
import { TextButton } from '../Link/TextButton'
import { Spacer } from '../Spacer/Spacer'
import { Typography } from '../Typography/Typography'
import { useThemeTokens } from '../ThemeProvider/useThemeTokens'
import { useViewport } from '../ViewportProvider/useViewport'

export const ModalContent = React.forwardRef(
  (
    {
      heading,
      headingLevel = 'h3',
      subHeading,
      subHeadingSize = 'medium',
      bodyText,
      confirmButtonText,
      confirmButtonVariant = { priority: 'high' },
      onConfirm,
      tokens,
      variant,
      cancelButtonText,
      cancelButtonType: CancelButton = TextButton,
      children,
      onCancel,
      footer
    },
    ref
  ) => {
    const viewport = useViewport()
    const { headingColor, cancelButtonColor, ...themeTokens } = useThemeTokens(
      'Modal',
      tokens,
      variant,
      { viewport }
    )
    const [scrollContainerHeight, setScrollContainerHeight] = React.useState(0)
    const [scrollContentHeight, setScrollContentHeight] = React.useState(0)

    const handleContainerLayout = ({
      nativeEvent: {
        layout: { height }
      }
    }) => setScrollContainerHeight(height)
    const onContentSizeChange = (_, height) => setScrollContentHeight(height)
    const isContentOverflowing = scrollContentHeight > scrollContainerHeight

    const hasConfirmButton = confirmButtonText !== undefined && onConfirm !== undefined
    const hasCancelButton = cancelButtonText !== undefined && onCancel !== undefined
    const hasHeadingSection = Boolean(heading || subHeading)

    const selectHeadingContainerStyles = ({
      paddingLeft,
      paddingRight,
      marginLeft,
      marginRight,
      borderColor,
      headingBorderBottomWidth,
      headingPaddingRight,
      headingPaddingTop
    }) => ({
      flexDirection: 'column',
      marginLeft: -marginLeft,
      marginRight: -marginRight,
      paddingLeft,
      paddingTop: headingPaddingTop,
      paddingRight: paddingRight + headingPaddingRight,
      borderBottomColor: borderColor,
      borderBottomWidth: headingBorderBottomWidth
    })

    const selectFooterContainerStyles = ({
      paddingLeft,
      paddingRight,
      paddingTop,
      marginLeft,
      marginRight,
      borderColor,
      gap,
      direction,
      footerTopWidth,
      hasBorder
    }) => ({
      flexDirection: direction,
      alignItems: 'center',
      gap,
      marginLeft: -marginLeft,
      marginRight: -marginRight,
      paddingLeft,
      paddingRight,
      paddingTop,
      borderTopWidth: footerTopWidth > 0 ? footerTopWidth : (hasBorder && 1) || 0,
      borderTopColor: borderColor
    })

    const subheadingStyles = {
      marginTop: themeTokens.subHeadingMarginTop
    }

    return (
      <View style={styles.modalContent} ref={ref}>
        {hasHeadingSection && (
          <View style={selectHeadingContainerStyles(themeTokens)}>
            {heading && (
              <Typography
                variant={{ size: headingLevel }}
                tokens={{ color: headingColor }}
                heading={headingLevel}
              >
                {heading}
              </Typography>
            )}
            {subHeading && (
              <View style={subheadingStyles}>
                <Typography variant={{ size: subHeadingSize }}>{subHeading}</Typography>
              </View>
            )}
            {Boolean((bodyText || children) && hasHeadingSection) && <Spacer space={3} />}
          </View>
        )}
        {bodyText && (
          <Box
            scroll={{ onContentSizeChange, showsVerticalScrollIndicator: true }}
            onLayout={handleContainerLayout}
            top={themeTokens.contentPaddingTop}
            bottom={themeTokens.contentPaddingBottom}
          >
            <Typography>{bodyText}</Typography>
          </Box>
        )}
        {children}
        {(hasConfirmButton || hasCancelButton) && !footer && (
          <View
            style={[
              selectFooterContainerStyles({
                ...themeTokens,
                hasBorder: isContentOverflowing
              })
            ]}
          >
            {hasConfirmButton && (
              <Button
                variant={confirmButtonVariant}
                tokens={{ width: viewport === 'xs' || viewport === 'sm' ? '100%' : undefined }}
                onPress={onConfirm}
              >
                {confirmButtonText}
              </Button>
            )}
            {hasCancelButton ? (
              <View style={styles.cancelButton}>
                <CancelButton tokens={{ color: cancelButtonColor }} onPress={onCancel}>
                  {cancelButtonText}
                </CancelButton>
              </View>
            ) : null}
          </View>
        )}
        {footer}
      </View>
    )
  }
)

ModalContent.displayName = 'ModalContent'

const styles = StyleSheet.create({
  modalContent: {
    flex: 1,
    flexDirection: 'column',
    minHeight: Platform.OS === 'web' ? '100%' : 'auto'
  },
  cancelButton: {
    display: 'flex'
  }
})

ModalContent.propTypes = {
  tokens: PropTypes.object,
  variant: PropTypes.object,
  heading: PropTypes.string,
  headingLevel: PropTypes.oneOf(['h3', 'h4']),
  subHeading: PropTypes.string,
  subHeadingSize: PropTypes.oneOf(['small', 'medium', 'large']),
  bodyText: PropTypes.string,
  confirmButtonText: PropTypes.string,
  confirmButtonVariant: PropTypes.object,
  onConfirm: PropTypes.func,
  cancelButtonText: PropTypes.string,
  cancelButtonType: PropTypes.elementType, // TODO: figure out a way of passing an icon to the TextButton
  children: PropTypes.node,
  onCancel: PropTypes.func,
  footer: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)])
}
