import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons';
import type { ComponentProps } from 'react';
import { useTheme } from '../../theme';

/** Toast 类型：分别映射主题语义色 success / error / info */
export type ToastType = 'success' | 'error' | 'info';

interface ToastAction {
  label: string;
  onPress: () => void;
}

interface ToastItem {
  /** 自增 id：区分连续触发，保证 effect 可靠重跑 */
  key: number;
  message: string;
  type: ToastType;
  action?: ToastAction;
}

interface ToastContextValue {
  showToast: (message: string, type?: ToastType, action?: ToastAction) => void;
}

const ToastContext = createContext<ToastContextValue | null>(null);

/** Toast 展示时长（ms） */
const TOAST_DURATION = 2500;
/** 带操作按钮（如撤销）时的展示时长（ms），更长以便用户反应 */
const ACTION_DURATION = 4500;
/** 淡入淡出动画时长（ms） */
const FADE_DURATION = 220;

/** 各类型对应的 Ionicons 图标 */
const TOAST_ICONS: Record<ToastType, ComponentProps<typeof Ionicons>['name']> = {
  success: 'checkmark-circle',
  error: 'alert-circle',
  info: 'information-circle',
};

/**
 * 全局轻量 Toast 提供者。
 *
 * 使用方式：
 *   <ToastProvider>...</ToastProvider>   // 需位于 ThemeProvider 与 SafeAreaProvider 之内
 *   const { showToast } = useToast();
 *   showToast('保存成功', 'success');
 *
 * - 自动 2.5s 消失，带淡入淡出 + 轻微下滑入场动画（Animated）
 * - 定位在屏幕顶部安全区下方，覆盖层 pointerEvents="none" 不拦截底层交互
 * - 连续触发时取消旧计时器并直接替换文案，避免闪烁
 */
export function ToastProvider({ children }: { children: React.ReactNode }) {
  const { theme } = useTheme();
  const insets = useSafeAreaInsets();

  const [toast, setToast] = useState<ToastItem | null>(null);
  const opacity = useRef(new Animated.Value(0)).current;
  const translateY = useRef(new Animated.Value(-12)).current;
  const hideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
  /** 当前是否有可见 Toast（决定新消息是否播放入场动画） */
  const visibleRef = useRef(false);
  const keyRef = useRef(0);

  const showToast = useCallback((message: string, type: ToastType = 'info', action?: ToastAction) => {
    keyRef.current += 1;
    setToast({ key: keyRef.current, message, type, action });
  }, []);

  const contextValue = useMemo(() => ({ showToast }), [showToast]);

  useEffect(() => {
    if (!toast) return;

    // 取消上一条尚未结束的隐藏计时器
    if (hideTimer.current) clearTimeout(hideTimer.current);

    if (visibleRef.current) {
      // 已有可见 Toast：仅替换文案并保持可见，避免闪烁
      opacity.setValue(1);
      translateY.setValue(0);
    } else {
      // 入场动画：淡入 + 轻微下滑
      visibleRef.current = true;
      opacity.setValue(0);
      translateY.setValue(-12);
      Animated.parallel([
        Animated.timing(opacity, {
          toValue: 1,
          duration: FADE_DURATION,
          useNativeDriver: true,
        }),
        Animated.spring(translateY, {
          toValue: 0,
          tension: 140,
          friction: 10,
          useNativeDriver: true,
        }),
      ]).start();
    }

    // 2.5s 后自动淡出并卸载
    hideTimer.current = setTimeout(() => {
      Animated.parallel([
        Animated.timing(opacity, {
          toValue: 0,
          duration: FADE_DURATION,
          useNativeDriver: true,
        }),
        Animated.timing(translateY, {
          toValue: -12,
          duration: FADE_DURATION,
          useNativeDriver: true,
        }),
      ]).start(() => {
        visibleRef.current = false;
        setToast(null);
      });
    }, toast.action ? ACTION_DURATION : TOAST_DURATION);

    return () => {
      if (hideTimer.current) clearTimeout(hideTimer.current);
    };
  }, [toast, opacity, translateY]);

  // 类型 → 语义背景色映射
  const toastBg: Record<ToastType, string> = {
    success: theme.colors.success,
    error: theme.colors.error,
    info: theme.colors.info,
  };

  return (
    <ToastContext.Provider value={contextValue}>
      <View style={styles.root}>
        {children}

        {toast && (
          <View
            pointerEvents={toast.action ? 'box-none' : 'none'}
            style={[styles.host, { top: insets.top + theme.spacing.sm }]}
          >
            <Animated.View
              accessibilityRole="alert"
              accessibilityLiveRegion="polite"
              style={[
                styles.toast,
                {
                  opacity,
                  transform: [{ translateY }],
                  backgroundColor: toastBg[toast.type],
                  borderRadius: theme.radii.md,
                  padding: theme.spacing.md,
                  gap: theme.spacing.xs,
                  ...theme.shadows.md,
                },
              ]}
            >
              <Ionicons
                name={TOAST_ICONS[toast.type]}
                size={theme.typography.bodySmall.fontSize + 4}
                color={theme.colors.fgInverse}
              />
              <Text
                style={{
                  color: theme.colors.fgInverse,
                  fontSize: theme.typography.bodySmall.fontSize,
                  fontWeight: theme.typography.bodySmall.fontWeight,
                  lineHeight: theme.typography.bodySmall.lineHeight,
                }}
              >
                {toast.message}
              </Text>
              {toast.action ? (
                <Pressable
                  accessibilityRole="button"
                  accessibilityLabel={toast.action.label}
                  onPress={() => {
                    if (hideTimer.current) clearTimeout(hideTimer.current);
                    visibleRef.current = false;
                    const act = toast.action;
                    setToast(null);
                    act?.onPress();
                  }}
                  style={{ marginLeft: theme.spacing.sm, paddingVertical: theme.spacing.xs, paddingHorizontal: theme.spacing.sm, borderRadius: theme.radii.sm, backgroundColor: 'rgba(255,255,255,0.22)' }}
                >
                  <Text style={{ color: theme.colors.fgInverse, fontSize: theme.typography.bodySmall.fontSize, fontWeight: '700' }}>
                    {toast.action.label}
                  </Text>
                </Pressable>
              ) : null}
            </Animated.View>
          </View>
        )}
      </View>
    </ToastContext.Provider>
  );
}

/** 获取全局 Toast 派发器（必须在 ToastProvider 内使用） */
export function useToast(): ToastContextValue {
  const ctx = useContext(ToastContext);
  if (!ctx) {
    throw new Error('useToast 必须在 ToastProvider 内部使用');
  }
  return ctx;
}

const styles = StyleSheet.create({
  root: { flex: 1 },
  host: {
    position: 'absolute',
    left: 0,
    right: 0,
    alignItems: 'center',
    zIndex: 999,
    elevation: 999,
  },
  toast: {
    flexDirection: 'row',
    alignItems: 'center',
    maxWidth: '86%',
  },
});
