import { memo, useCallback } from 'react'
import { Pressable } from 'react-native'
import Animated, {
  measure,
  runOnUI,
  useAnimatedReaction,
  useAnimatedRef,
  useAnimatedStyle,
  useSharedValue,
  withSpring,
} from 'react-native-reanimated'
import type { MastodonList } from 'src/lib/api/mastodon'
import { Text, useTheme, YStack } from 'tamagui'
import { useOrganizerDrag } from './organizerDrag'

// Right-rail colour token — the drop target. Mirrors FediverseLists'
// `ListTargetView`: a 56 dp circle filled with the list's OKLab palette colour
// (white 2-char prefix), springing to scale 1.10 + a deeper shadow while it's
// the hovered drop target. The circle's on-screen frame is measured into the
// shared `tokenFrames` registry on layout and on every rail-scroll tick so the
// drag hit-test (which runs in the row's pan worklet) can find it; off-screen
// recycled/scrolled tokens simply measure null and don't participate until
// they're visible again.

const TOKEN = 56
const HIT_SLOP = 10
const TOKEN_SPRING = { damping: 18, stiffness: 240, mass: 0.55 } as const

type Props = {
  list: MastodonList
  color: string
  onPress: (listId: string) => void
}

function OrganizerListTokenImpl({ list, color, onPress }: Props) {
  const theme = useTheme()
  const { hoveredListId, tokenFrames, railScrollY } = useOrganizerDrag()
  const circleRef = useAnimatedRef<Animated.View>()
  const scale = useSharedValue(1)
  const shadowOpacity = useSharedValue(0.12)

  const writeFrame = useCallback(() => {
    'worklet'
    const m = measure(circleRef)
    if (m) {
      tokenFrames.value = {
        ...tokenFrames.value,
        [list.id]: {
          pageX: m.pageX - HIT_SLOP,
          pageY: m.pageY - HIT_SLOP,
          width: m.width + HIT_SLOP * 2,
          height: m.height + HIT_SLOP * 2,
        },
      }
    }
  }, [circleRef, tokenFrames, list.id])

  // Re-measure whenever the rail scrolls so the frame stays accurate.
  useAnimatedReaction(
    () => railScrollY.value,
    () => writeFrame()
  )

  // Spring the token while it's the hovered drop target.
  useAnimatedReaction(
    () => hoveredListId.value === list.id,
    (targeted, prev) => {
      if (targeted === prev) return
      scale.value = withSpring(targeted ? 1.1 : 1, TOKEN_SPRING)
      shadowOpacity.value = withSpring(targeted ? 0.3 : 0.12, TOKEN_SPRING)
    }
  )

  const circleStyle = useAnimatedStyle(() => {
    const targeted = hoveredListId.value === list.id
    return {
      transform: [{ scale: scale.value }],
      shadowOpacity: shadowOpacity.value,
      borderWidth: targeted ? 2 : 0,
    }
  })

  const prefix = list.title.trim().slice(0, 2).toUpperCase() || '··'

  return (
    <YStack alignItems="center" gap={6} width={TOKEN + 24}>
      <Pressable
        testID={`organizer-list-token-${list.id}`}
        onPress={() => onPress(list.id)}
        onLayout={() => runOnUI(writeFrame)()}
        accessibilityRole="button"
        accessibilityLabel={`${list.title}. Tap to manage, or drop an account here to add them.`}
      >
        <Animated.View
          ref={circleRef}
          collapsable={false}
          style={[
            {
              width: TOKEN,
              height: TOKEN,
              borderRadius: TOKEN / 2,
              backgroundColor: color,
              alignItems: 'center',
              justifyContent: 'center',
              borderColor: theme.background.val,
              shadowColor: '#000',
              shadowRadius: 8,
              shadowOffset: { width: 0, height: 3 },
            },
            circleStyle,
          ]}
        >
          <Text
            color="white"
            fontSize={17}
            fontWeight="700"
            style={{
              textShadowColor: 'rgba(0,0,0,0.25)',
              textShadowRadius: 2,
              textShadowOffset: { width: 0, height: 1 },
            }}
          >
            {prefix}
          </Text>
        </Animated.View>
      </Pressable>
      <Text
        width={70}
        textAlign="center"
        fontSize="$caption"
        color="$colorSecondary"
        numberOfLines={1}
      >
        {list.title}
      </Text>
    </YStack>
  )
}

export const OrganizerListToken = memo(OrganizerListTokenImpl)
