import {useRef, useState} from 'react'
import {Modal, Pressable, StyleSheet, View} from 'react-native'
import Animated, {
  interpolate,
  runOnJS,
  useAnimatedStyle,
  useSharedValue,
  withSpring,
  withTiming,
} from 'react-native-reanimated'
import {useLingui} from '@lingui/react/macro'

import {atoms as a} from '#/alf'
import {ArrowShareRight_Stroke2_Corner2_Rounded as ShareIcon} from '#/components/icons/ArrowShareRight'
import {type Props as IconProps} from '#/components/icons/common'
import {DotGrid3x1_Stroke2_Corner0_Rounded as DotsIcon} from '#/components/icons/DotGrid'
import {Download_Stroke2_Corner0_Rounded as DownloadIcon} from '#/components/icons/Download'
import {Text} from '#/components/Typography'
import {CircleChromeButton} from './CircleChromeButton'

type Props = {
  onPressShare: () => void
  onPressSave: () => void
}

type Anchor = {x: number; y: number; width: number; height: number}

const GAP = 6
const CARD_BG = '#000000'
const CARD_BORDER = '#232e3e'
const ITEM_TEXT = '#f9fafb'

const SPRING_IN = {damping: 18, mass: 0.6, stiffness: 240}
const TIMING_OUT = {duration: 150}

export function ImageMenu({onPressShare, onPressSave}: Props) {
  const {t: l} = useLingui()
  const triggerRef = useRef<View>(null)
  const [isMounted, setIsMounted] = useState(false)
  const [anchor, setAnchor] = useState<Anchor | null>(null)
  const progress = useSharedValue(0)

  const open = () => {
    triggerRef.current?.measureInWindow((x, y, width, height) => {
      setAnchor({x, y, width, height})
      setIsMounted(true)
      progress.set(withSpring(1, SPRING_IN))
    })
  }

  const close = () => {
    progress.set(
      withTiming(0, TIMING_OUT, finished => {
        if (finished) {
          runOnJS(setIsMounted)(false)
        }
      }),
    )
  }

  const runAction = (action: () => void) => {
    close()
    action()
  }

  return (
    <>
      <View ref={triggerRef} collapsable={false}>
        <CircleChromeButton
          icon={DotsIcon}
          iconStyle={{transform: [{rotate: '90deg'}]}}
          label={l`Image options`}
          onPress={open}
        />
      </View>
      <Modal
        transparent
        visible={isMounted}
        animationType="none"
        onRequestClose={close}
        statusBarTranslucent>
        <Pressable
          accessibilityRole="button"
          accessibilityLabel={l`Close menu`}
          accessibilityHint=""
          style={[a.absolute, a.inset_0]}
          onPress={close}
        />
        {anchor && (
          <MenuCard anchor={anchor} progress={progress}>
            <MenuItem
              icon={ShareIcon}
              label={l`Share image`}
              onPress={() => runAction(onPressShare)}
            />
            <MenuItem
              icon={DownloadIcon}
              label={l`Save image`}
              onPress={() => runAction(onPressSave)}
            />
          </MenuCard>
        )}
      </Modal>
    </>
  )
}

function MenuCard({
  anchor,
  progress,
  children,
}: {
  anchor: Anchor
  progress: ReturnType<typeof useSharedValue<number>>
  children: React.ReactNode
}) {
  const animatedStyle = useAnimatedStyle(() => ({
    opacity: progress.get(),
    transform: [{scale: interpolate(progress.get(), [0, 1], [0.9, 1])}],
  }))

  return (
    <Animated.View
      style={[
        a.absolute,
        a.self_start,
        styles.card,
        {
          top: anchor.y + anchor.height + GAP,
          left: anchor.x,
          transformOrigin: 'top left',
        },
        animatedStyle,
      ]}>
      {children}
    </Animated.View>
  )
}

function MenuItem({
  icon: Icon,
  label,
  onPress,
}: {
  icon: React.ComponentType<IconProps>
  label: string
  onPress: () => void
}) {
  return (
    <Pressable
      accessibilityRole="button"
      accessibilityLabel={label}
      accessibilityHint=""
      onPress={onPress}
      style={({pressed}) => [styles.item, pressed && styles.itemPressed]}>
      <Icon width={18} fill={ITEM_TEXT} />
      <Text style={styles.itemText}>{label}</Text>
    </Pressable>
  )
}

const styles = StyleSheet.create({
  card: {
    padding: 8,
    borderRadius: 16,
    borderWidth: 0.5,
    borderColor: CARD_BORDER,
    backgroundColor: CARD_BG,
    shadowColor: '#000',
    shadowOffset: {width: 0, height: 4},
    shadowOpacity: 0.16,
    shadowRadius: 20,
    elevation: 8,
  },
  item: {
    height: 44,
    paddingHorizontal: 12,
    borderRadius: 8,
    flexDirection: 'row',
    alignItems: 'center',
    gap: 6,
  },
  itemPressed: {
    backgroundColor: 'rgba(255, 255, 255, 0.08)',
  },
  itemText: {
    fontSize: 15,
    fontWeight: '500',
    lineHeight: 19.5,
    color: ITEM_TEXT,
  },
})
