import React from 'react'
import PropTypes from 'prop-types'
import { View, StyleSheet, Platform } from 'react-native'
import { Portal as GorhomPortal } from '@gorhom/portal'
import { Portal as LocalPortal } from '../Portal/Portal'
import { useCopy } from '../utils/useCopy'
import { copyPropTypes } from '../utils/props/copyPropTypes'
import { getTokensPropType } from '../utils/props/tokens'
import { variantProp } from '../utils/props/variantProp'
import { useViewport } from '../ViewportProvider/useViewport'
import { useThemeTokens } from '../ThemeProvider/useThemeTokens'
import { dictionary } from './dictionary'

import { Card } from '../Card/Card'
import { IconButton } from '../IconButton/IconButton'
import { useDetectOutsideClick } from '../utils/useDetectOutsideClick'

const staticStyles = StyleSheet.create({
  positioner: {
    flex: 1, // Grow to maxWidth when possible, shrink when not possible
    zIndex: 10000, // Position on top of all the other overlays, including backdrops and modals,
    elevation: 10000, // Position on top of all the other overlays, including backdrops and modals,
    borderRadius: 4,
    ...Platform.select({
      web: {
        boxShadow: 'rgba(0, 0, 0, 0.1) 0px 4px 8px 0px'
      },
      default: {
        shadowColor: 'rgba(0, 0, 0, 0.1)',
        shadowOffset: { width: 0, height: 4 },
        shadowOpacity: 1,
        shadowRadius: 8
      }
    })
  },
  card: {
    paddingLeft: 0,
    paddingRight: 0,
    paddingTop: 0,
    paddingBottom: 0
  },
  closeButtonContainer: {
    position: 'absolute',
    top: 0,
    right: 0,
    zIndex: 1
  },
  hidden: {
    // Use opacity not visibility to hide the dropdown during positioning
    // so on web, children may be focused from the first render
    opacity: 0
  }
})

const selectContainerStyle = (enableFullscreen, themeTokens) => ({
  borderColor: themeTokens.borderColor,
  backgroundColor: themeTokens.backgroundColor,
  ...Platform.select({
    web: {
      position: enableFullscreen ? 'fixed' : 'absolute'
    },
    default: {
      position: 'absolute'
    }
  })
})

const selectCloseButtonContainerStyles = ({ paddingRight, paddingTop }) => ({
  paddingRight,
  paddingTop
})

export const ModalOverlay = React.forwardRef(
  (
    {
      children,
      isReady = false,
      maxHeight,
      maxHeightSize,
      maxWidthSize,
      minHeight,
      minWidth,
      overlaidPosition,
      onLayout,
      variant,
      tokens,
      copy,
      onClose,
      enableFullscreen = false
    },
    ref
  ) => {
    const viewport = useViewport()
    const themeTokens = useThemeTokens('Modal', tokens, variant, { viewport, maxWidth: false })

    const containerRef = React.useRef(ref || null)
    useDetectOutsideClick(containerRef, onClose)

    const containerWidthHeight = {
      minWidth: tokens.maxWidth ? maxWidthSize : minWidth,
      minHeight: maxHeight ? maxHeightSize : minHeight,
      maxWidth: maxWidthSize,
      maxHeight: maxHeightSize
    }

    const { closeIcon: CloseIconComponent, backgroundColor } = themeTokens

    const getCopy = useCopy({ dictionary, copy })
    const closeLabel = getCopy('closeButton')

    // On web, use the local Portal (always appends to document.body) to ensure correct
    // absolute positioning in MFE/iframe contexts. @gorhom/portal may render its host
    // outside the iframe's document, causing coordinate mismatches when scrolled.
    const PortalComponent = Platform.OS === 'web' ? LocalPortal : GorhomPortal

    return (
      <PortalComponent>
        <View
          ref={containerRef}
          onLayout={onLayout}
          style={[
            overlaidPosition,
            containerWidthHeight,
            staticStyles.positioner,
            !isReady && staticStyles.hidden,
            selectContainerStyle(enableFullscreen, themeTokens)
          ]}
        >
          <Card tokens={{ ...staticStyles.card, backgroundColor }}>
            <View
              style={[
                staticStyles.closeButtonContainer,
                selectCloseButtonContainerStyles(themeTokens)
              ]}
            >
              <IconButton
                onPress={onClose}
                icon={CloseIconComponent}
                accessibilityRole="button"
                accessibilityLabel={closeLabel}
              />
            </View>
            {children}
          </Card>
        </View>
      </PortalComponent>
    )
  }
)

ModalOverlay.displayName = 'ModalOverlay'

ModalOverlay.propTypes = {
  children: PropTypes.node.isRequired,
  isReady: PropTypes.bool,
  overlaidPosition: PropTypes.shape({
    top: PropTypes.number,
    left: PropTypes.number,
    width: PropTypes.number
  }),
  minWidth: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  minHeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  maxHeightSize: PropTypes.number,
  maxWidthSize: PropTypes.number,
  maxHeight: PropTypes.bool,
  maxWidth: PropTypes.bool,
  onLayout: PropTypes.func,
  variant: variantProp.propType,
  tokens: getTokensPropType('Modal'),
  copy: copyPropTypes,
  onClose: PropTypes.func,
  enableFullscreen: PropTypes.bool
}
