import { View } from '@tarojs/components'
import Taro from '@tarojs/taro'
import { nextTick } from '@tarojs/runtime'
import classNames from 'classnames'
import { forwardRef, useCallback, useEffect, useId, useImperativeHandle, useMemo, useRef, useState, useTransition } from 'react'
import IconFont from '../iconfont/iconfont'
import styles from './index.module.scss'

const SystemWidth = Taro.getSystemInfoSync().windowWidth

const arrowSize = 32

// 由于taro自动把px编译成rpx，所以这里需要把单位处理一下 转成真正的px
const convertPx = (px: number) => {
  const realPx = (px / 750) * SystemWidth
  return realPx
}

type Placement =
  | 'top'
  | 'top-start'
  | 'top-end'
  | 'right'
  | 'right-start'
  | 'right-end'
  | 'bottom'
  | 'bottom-start'
  | 'bottom-end'
  | 'left'
  | 'left-start'
  | 'left-end'

interface ToolTipEvent {
  onVisibleChange?: (visible?: boolean) => void
}

interface ToolTipPropsType extends ToolTipEvent {
  defaultVisible?: boolean
  content: React.ReactNode
  placement?: Placement
  children?: React.ReactNode
  customClassName?: string
  customStyle?: React.CSSProperties
  customContentStyle?: React.CSSProperties
}

interface ToolTipRef {
  show: () => void
  hide: () => void
  visible: boolean
}

const popoverStyle = {
  color: '#333333',
}

const ToolTip = (props: ToolTipPropsType, ref) => {
  const id = useId()
  const [, setForceUpdate] = useState({})
  const { placement = 'top-start', defaultVisible = false, onVisibleChange, children, content = '请填入提示信息', customClassName, customStyle, customContentStyle } = props

  if (!content) {
    throw new Error('tooltip: content 不能为空')
  }

  const [visible, setVisible] = useState(defaultVisible)

  const onVisibleChangeRef = useRef(onVisibleChange)
  onVisibleChangeRef.current = onVisibleChange

  // 暴露方法给外部
  useImperativeHandle(
    ref,
    () => {
      return {
        show: () => setVisible(true),
        hide: () => setVisible(false),
        visible,
      }
    },
    [visible],
  )

  const handleClick = useCallback(() => {
    setVisible((v) => {
      onVisibleChangeRef.current?.(!v)
      return !v
    })
  }, [])

  const handleClickMark = useCallback(() => {
    setVisible(false)
    onVisibleChangeRef.current?.(false)
  }, [])

  const getArrowSide = useMemo(() => {
    const side = placement.split('-')[0] as string // placement = 'top-start'  取 'top'

    const arrowSide = {
      top: 'bottom',
      right: 'left',
      bottom: 'top',
      left: 'right',
    }[side] as string
    return arrowSide
  }, [placement])

  const [childrenRect, setChildrenRect] = useState<any>({})
  const childrenRectRef = useRef(childrenRect)
  childrenRectRef.current = childrenRect

  const [viewport, setViewport] = useState<any>({})
  const viewportRef = useRef(viewport)
  viewportRef.current = viewport

  const contextRectRef = useRef<any>(null)

  useEffect(() => {
    if (visible && !contextRectRef.current) {
      nextTick(() => {
        const query = Taro.createSelectorQuery()
        query.select(`#content-${id}`).boundingClientRect((res) => {
          console.log('contextRectRef', res)
          contextRectRef.current = res
          setForceUpdate({})
        }).exec()
      })
    }
  }, [visible, contextRectRef.current])

  useEffect(() => {
    console.log('useLayoutEffect')
    const query = Taro.createSelectorQuery()
    query.select('#children').boundingClientRect()
    query.selectViewport().scrollOffset()
    query.exec((res) => {
      console.log(res[0])
      console.log(res[1])
      setChildrenRect(res[0])
      childrenRectRef.current = res[0]
      setViewport(res[1])
      viewportRef.current = res[1]
    })
  }, [])

  // 箭头 坐标
  const arrowCoords = useMemo(() => {
    const contextRect = contextRectRef.current
    // contextRect 没获取到之前  隐藏
    if (!contextRect) { return { top: '9999px' } }
    console.log('getArrowSide==>', getArrowSide, childrenRectRef.current)
    switch (getArrowSide) {
      case 'bottom': // 下箭头
        return {
          left: childrenRectRef.current.width / 2 - convertPx(arrowSize) / 2,
          top: -convertPx(arrowSize),
          right: '',
          bottom: '',
        }
      case 'left': // 左箭头
        return {
          left: childrenRectRef.current.width,
          right: '',
          top: childrenRectRef.current.height / 2 - convertPx(arrowSize) / 2,
          bottom: '',
        }
      case 'top': // 上箭头
        return {
          left: childrenRectRef.current.width / 2 - convertPx(arrowSize) / 2,
          right: '',
          top: childrenRectRef.current.height,
          bottom: '',
        }
      case 'right': // 右箭头
        return {
          left: -convertPx(arrowSize),
          right: '',
          top: childrenRectRef.current.height / 2 - convertPx(arrowSize) / 2,
          bottom: '',
        }
    }
  }, [getArrowSide, childrenRectRef.current, contextRectRef.current])

  // content 坐标
  const contentCoords = useMemo(() => {
    const placementSide = placement.split('-')[1] as string // placement = 'top-start'  取 'start'
    console.log('placementSide', placementSide)
    let coordsStyle = {}
    const contextRect = contextRectRef.current
    // contextRect 没获取到之前  隐藏
    if (!contextRect) { return { top: '9999px' } }
    console.log('contextRect', contextRect)
    const childrenRect = childrenRectRef.current
    switch (getArrowSide) {
      case 'bottom': // 下箭头
        coordsStyle = {
          bottom: convertPx(arrowSize) - 5,
          top: '',
        }
        if (placementSide === 'start') {
          return {
            ...coordsStyle,
            left: 0,
            right: '',
          }
        }
        else if (placementSide === 'end') {
          return {
            ...coordsStyle,
            left: '',
            right: 0,
          }
        }
        else {
          return {
            ...coordsStyle,
            left: `${-(contextRect?.width / 2 - childrenRect.width / 2)}px`,
            right: '',
          }
        }
      case 'left': // 左箭头
        coordsStyle = {
          left: childrenRect.width + convertPx(arrowSize) - 5,
          right: '',
        }
        if (placementSide === 'start') {
          return {
            ...coordsStyle,
            top: 0,
            bottom: '',
          }
        }
        else if (placementSide === 'end') {
          return {
            ...coordsStyle,
            top: '',
            bottom: `${-childrenRect.height}px`,
          }
        }
        else {
          return {
            ...coordsStyle,
            top: `${-(contextRect.height / 2 - childrenRect.height / 2)}px`,
            bottom: '',
          }
        }
      case 'top': // 上箭头
        coordsStyle = {
          top: childrenRect.height + convertPx(arrowSize) - 5,
          bottom: '',
        }
        if (placementSide === 'start') {
          return {
            ...coordsStyle,
            left: 0,
            right: '',
          }
        }
        else if (placementSide === 'end') {
          return {
            ...coordsStyle,
            left: '',
            right: 0,
          }
        }
        else {
          return {
            ...coordsStyle,
            left: `${-(contextRect?.width / 2 - childrenRect.width / 2)}px`,
            right: '',
          }
        }
      case 'right': // 右箭头
        coordsStyle = {
          left: '',
          right: convertPx(arrowSize) - 5,
        }
        if (placementSide === 'start') {
          return {
            ...coordsStyle,
            top: 0,
            bottom: '',
          }
        }
        else if (placementSide === 'end') {
          return {
            ...coordsStyle,
            top: '',
            bottom: `${-childrenRect.height}px`,
          }
        }
        else {
          return {
            ...coordsStyle,
            top: `${-(contextRect.height / 2 - childrenRect.height / 2)}px`,
            bottom: '',
          }
        }
    }
  }, [getArrowSide, childrenRectRef.current, contextRectRef.current])

  const ContentComponent = useMemo(() => {
    return (
      <View className={classNames(styles.tooltip, visible ? '' : styles['tooltip-hidden'], customClassName)} style={customStyle}>
        {/* 箭头 */}
        <View className={classNames(styles.arrowIcon, styles[`arrowIcon-${getArrowSide}`])} style={arrowCoords}>
          <IconFont name="icon-shouqi1" size={arrowSize} color={popoverStyle.color}></IconFont>
        </View>
        {/* content */}
        <View className={styles['tooltip-inner']} id={`content-${id}`} style={{ ...contentCoords, ...customContentStyle }}>
          <View className={styles['tooltip-inner-content']}>{content}</View>
        </View>
      </View>
    )
  }, [content, getArrowSide, visible, arrowCoords, contentCoords])

  return (
    <>
      {/* 遮罩层 */}
      <View className={classNames(styles.mark, visible ? '' : styles['tooltip-hidden'])} onClick={handleClickMark}></View>
      <View className={styles['tooltip-container']}>
        <View onClick={handleClick} id="children">
          {children}
        </View>
        {ContentComponent}
      </View>
    </>
  )
}

export default forwardRef<ToolTipRef, ToolTipPropsType>(ToolTip)
