import { memo, useCallback, useMemo } from 'react';
import { Text } from '@/aesthetics/Text';
import { buttonHeight, font, radius, spacing, useColors } from '@/aesthetics/styles';
import { Check, X } from 'lucide-react-native';
import { StyleSheet, View } from 'react-native';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, {
  FadeInDown,
  FadeOut,
  Layout,
  runOnJS,
  useAnimatedStyle,
  useSharedValue,
  withTiming,
} from 'react-native-reanimated';
import { useHaptics } from '@/aesthetics/useHaptics';
import { useStrings } from '@/common/hooks/useStrings';
import { TYPE_ICONS, SWIPE_THRESHOLD, formatValue } from './constants';
import { getTimeAgo } from '@/common/utils/format';
import type { MemoLog } from './types';

type MemoLogCardProps = {
  entry: MemoLog;
  onRequestDelete: () => void;
  onPress: () => void;
  index: number;
};

export const MemoLogCard = memo(function MemoLogCard({
  entry,
  onRequestDelete,
  onPress,
  index,
}: MemoLogCardProps) {
  const c = useColors();
  const strings = useStrings();
  const { notification, impact, NotificationType, ImpactStyle } = useHaptics();

  const getDisplayValue = (e: MemoLog): string | null => {
    if (e.type === 'check')
      return e.value === 1 ? strings.userCustomLogs.yes : strings.userCustomLogs.no;
    if (e.type === 'number') return formatValue(e.value, e.valueUnit);
    return String(e.value);
  };
  const translateX = useSharedValue(0);
  const hasPassedThreshold = useSharedValue(false);
  const IconComponent = TYPE_ICONS[entry.type];

  const triggerDeleteConfirm = useCallback(() => {
    notification(NotificationType.Success);
    onRequestDelete();
  }, [notification, NotificationType, onRequestDelete]);

  const triggerHaptic = useCallback(() => {
    impact(ImpactStyle.Medium);
  }, [impact, ImpactStyle]);

  const tapGesture = useMemo(
    () =>
      Gesture.Tap().onEnd(() => {
        'worklet';
        runOnJS(onPress)();
      }),
    [onPress]
  );

  const panGesture = useMemo(
    () =>
      Gesture.Pan()
        .activeOffsetX([-10, 10])
        .failOffsetY([-20, 20])
        .onUpdate(e => {
          'worklet';
          const clampedX = Math.min(0, Math.max(-120, e.translationX));
          translateX.value = clampedX;
          if (clampedX <= -SWIPE_THRESHOLD && !hasPassedThreshold.value) {
            hasPassedThreshold.value = true;
            runOnJS(triggerHaptic)();
          } else if (clampedX > -SWIPE_THRESHOLD) {
            hasPassedThreshold.value = false;
          }
        })
        .onEnd(e => {
          'worklet';
          hasPassedThreshold.value = false;
          if (e.translationX <= -SWIPE_THRESHOLD) {
            runOnJS(triggerDeleteConfirm)();
          } else {
            translateX.value = withTiming(0, { duration: 200 });
          }
        }),
    [translateX, hasPassedThreshold, triggerDeleteConfirm, triggerHaptic]
  );

  const composedGesture = useMemo(
    () => Gesture.Race(tapGesture, panGesture),
    [tapGesture, panGesture]
  );

  const rowStyle = useAnimatedStyle(() => ({
    transform: [{ translateX: translateX.value }],
  }));

  const deleteStyle = useAnimatedStyle(() => ({
    opacity: Math.min(1, Math.abs(translateX.value) / SWIPE_THRESHOLD),
  }));

  const timeAgo = getTimeAgo(entry.timestamp);

  return (
    <Animated.View entering={FadeInDown.delay(index * 50)} exiting={FadeOut} layout={Layout}>
      <View style={styles.swipeContainer}>
        <Animated.View style={[styles.swipeDeleteBg, { backgroundColor: c.danger }, deleteStyle]}>
          <Text style={[styles.swipeDeleteText, { color: c.buttonText }]}>
            {strings.userCustomLogs.delete}
          </Text>
        </Animated.View>
        <GestureDetector gesture={composedGesture}>
          <Animated.View style={[styles.entryRow, { backgroundColor: c.tagBg }, rowStyle]}>
            <View style={styles.entryIconWrap}>
              {entry.icon ? (
                <Text style={styles.entryIcon}>{entry.icon}</Text>
              ) : entry.type === 'check' ? (
                entry.value === 1 ? (
                  <Check size={16} color={c.success} strokeWidth={2.5} />
                ) : (
                  <X size={16} color={c.danger} strokeWidth={2.5} />
                )
              ) : IconComponent ? (
                <IconComponent size={16} color={c.logger} strokeWidth={2} />
              ) : null}
            </View>
            <View style={styles.entryContent}>
              <Text style={[styles.entryName, { color: c.text }]} numberOfLines={1}>
                {entry.title}
              </Text>
              <Text style={[styles.entryValue, { color: c.secondaryText }]} numberOfLines={1}>
                {getDisplayValue(entry)}
              </Text>
            </View>
            <Text style={[styles.entryTime, { color: c.tertiaryText }]}>{timeAgo}</Text>
          </Animated.View>
        </GestureDetector>
      </View>
    </Animated.View>
  );
});

const styles = StyleSheet.create({
  swipeContainer: { position: 'relative', overflow: 'hidden', borderRadius: radius.md },
  swipeDeleteBg: {
    position: 'absolute',
    right: 0,
    top: 0,
    bottom: 0,
    width: 120,
    alignItems: 'center',
    justifyContent: 'center',
    borderTopRightRadius: radius.md,
    borderBottomRightRadius: radius.md,
  },
  swipeDeleteText: { fontSize: font.sm, fontWeight: '600' },
  entryRow: {
    flexDirection: 'row',
    alignItems: 'center',
    minHeight: buttonHeight.md,
    borderRadius: radius.md,
    overflow: 'hidden',
  },
  entryIconWrap: {
    width: 32,
    alignItems: 'center',
    justifyContent: 'center',
    marginLeft: spacing.md,
  },
  entryIcon: { fontSize: 16 },
  entryContent: { flex: 1, paddingVertical: spacing.sm, paddingHorizontal: spacing.sm },
  entryName: { fontSize: font.sm, fontWeight: '500' },
  entryValue: { fontSize: font.xs, marginTop: 2 },
  entryTime: { fontSize: font.xs, marginRight: spacing.md },
});
