import { useEffect, useLayoutEffect, useMemo, useState, useCallback, useRef } from 'react';
import {
  StyleSheet,
  View,
  Text,
  Pressable,
  PanResponder,
  AppState,
  Animated as RNAnimated,
  ImageBackground,
  Platform,
  useWindowDimensions,
} from 'react-native';
import { useTranslation } from 'react-i18next';
import { useFocusEffect } from 'expo-router';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import Animated, {
  Easing,
  runOnJS,
  useAnimatedStyle,
  useSharedValue,
  withSequence,
  withTiming,
} from 'react-native-reanimated';

import { MOCK_CONTENT } from '@/src/constants/mockContent';
import {
  addFavorite,
  getThemeMode,
  getUserProfile,
  setReaction,
  setThemeMode,
  clearPendingHomePushMessage,
  getPendingHomePushMessage,
  getRecoFeedCache,
  setRecoFeedCache,
  getUserProfileScoring,
  getRecoFeedHistory,
  recordRecoFeedServed,
  type ThemeMode,
  getSuixinThemeState,
  setSuixinThemeState,
  type SuixinThemeStateV1,
} from '@/src/storage/appStorage';

import { fetchRecoFeed } from '@/src/services/recoApi';
import { subscribeHomePushMessage } from '@/src/services/pushNotificationRoute';
import { toBackendLocaleFromLanguageTag } from '@/src/i18n/locale';

import ProfileModal from '@/components/home/ProfileModal';
import ThemeModal from '@/components/home/ThemeModal';

import ThemeIcon from '@/assets/images/home/theme.svg';
import MyIcon from '@/assets/images/home/my.svg';
import LikeFilledIcon from '@/assets/images/home/like_filled.svg';
import LikeIcon from '@/assets/images/icon/like_icon.svg';

import { getBootId } from '@/src/utils/bootSession';
import { advanceSuixinState, buildInitialSuixinState, NEUTRAL_THEME_COLORS } from '@/src/features/suixinTheme';
import { wrapText } from '@/src/features/textWrap';
import { defaultMeasureWidthImpl } from '@/src/features/textWrap/measure';
import { ensureDailyWidgetRecoUpToDate } from '@/src/modules/dailyWidgetReco';

// 预定义风景图列表
const NATURE_IMAGES = [
  require('@/assets/theme/nature/1.png'),
  require('@/assets/theme/nature/2.png'),
  require('@/assets/theme/nature/3.png'),
  require('@/assets/theme/nature/4.png'),
  require('@/assets/theme/nature/5.png'),
  require('@/assets/theme/nature/6.png'),
  require('@/assets/theme/nature/7.png'),
  require('@/assets/theme/nature/8.png'),
  require('@/assets/theme/nature/9.png'),
  require('@/assets/theme/nature/10.png'),
  require('@/assets/theme/nature/11.png'),
  require('@/assets/theme/nature/12.png'),
  require('@/assets/theme/nature/13.png'),
  require('@/assets/theme/nature/14.png'),
  require('@/assets/theme/nature/15.png'),
  require('@/assets/theme/nature/17.png'),
  require('@/assets/theme/nature/18.png'),
  require('@/assets/theme/nature/19.png'),
  require('@/assets/theme/nature/20.png'),
  require('@/assets/theme/nature/22.png'),
];

// 预定义颜色列表
const THEME_COLORS = [
  '#F7D9BF',
  '#CBF2D8',
  '#F5CDDE',
  '#F2ECCB',
  '#E2CBF2',
  '#CBD9F2',
];

type FeedItem = { content_id: string; text: string };

export default function HomeScreen() {
  const { t, i18n } = useTranslation();
  const { width: windowWidth, height: windowHeight } = useWindowDimensions();
  const isEnglish = i18n.language?.startsWith('en');
  const isTablet = Platform.OS === 'ios' && Math.min(windowWidth, windowHeight) >= 768;
  const recoLang: 'en' | 'tc' = toBackendLocaleFromLanguageTag(i18n.language);
  const insets = useSafeAreaInsets();
  const [index, setIndex] = useState(0);
  const [themeMode, setThemeModeState] = useState<ThemeMode>('scenery');
  const [suixinBgColor, setSuixinBgColor] = useState<string>(NEUTRAL_THEME_COLORS[1]);
  const [themeOpen, setThemeOpen] = useState(false);
  const [profileOpen, setProfileOpen] = useState(false);
  const [profileName, setProfileName] = useState<string | undefined>(undefined);
  const [busy, setBusy] = useState(false);
  const [likeFilled, setLikeFilled] = useState(false);
  const [feedItems, setFeedItems] = useState<FeedItem[]>([]);
  const [pendingPushItem, setPendingPushItem] = useState<FeedItem | null>(null);
  const [isFetching, setIsFetching] = useState(false);
  const [cardWidth, setCardWidth] = useState<number | null>(null);
  const [wrappedText, setWrappedText] = useState<string>('');
  const wrapLogRef = useRef<{ key: string } | null>(null);
  const busyRef = useRef(false);
  const indexRef = useRef(0);
  const currentFeedRef = useRef<FeedItem[]>([]);
  const likedIdsRef = useRef<Set<string>>(new Set());
  const likeInFlightRef = useRef(false);

  const applyPendingPushItem = useCallback(async (message: { notification_id: string; content_id?: number; text: string }) => {
    const nextItem: FeedItem = {
      content_id: message.content_id != null ? String(message.content_id) : `push:${message.notification_id}`,
      text: message.text,
    };
    setPendingPushItem(nextItem);
    indexRef.current = 0;
    setIndex(0);
    setLikeFilled(likedIdsRef.current.has(String(nextItem.content_id)));
    await clearPendingHomePushMessage();
  }, []);

  const consumePendingPushItem = useCallback(async () => {
    const pendingMessage = await getPendingHomePushMessage();
    if (!pendingMessage?.text) return;
    await applyPendingPushItem(pendingMessage);
  }, [applyPendingPushItem]);

  useEffect(() => {
    busyRef.current = busy;
  }, [busy]);
  useEffect(() => {
    indexRef.current = index;
  }, [index]);

  // 解决语言切换时重复触发拉取/清空导致“文案不停跳动”的问题：
  // 用 ref 持有最新状态，避免 useCallback 依赖 feedItems/isFetching 造成函数 identity 变化 → effect 重复执行
  const feedItemsRef = useRef<FeedItem[]>([]);
  const isFetchingRef = useRef(false);
  const themeModeRef = useRef<ThemeMode>('scenery');
  const suixinStateRef = useRef<SuixinThemeStateV1 | null>(null);
  useEffect(() => {
    feedItemsRef.current = feedItems;
  }, [feedItems]);
  useEffect(() => {
    isFetchingRef.current = isFetching;
  }, [isFetching]);
  useEffect(() => {
    themeModeRef.current = themeMode;
  }, [themeMode]);

  const ensureSuixinReady = useCallback(async () => {
    const bootId = getBootId();
    const stored = await getSuixinThemeState();
    if (stored && stored.boot_id === bootId) {
      suixinStateRef.current = stored;
      setSuixinBgColor(stored.last_color || NEUTRAL_THEME_COLORS[1]);
      return stored;
    }

    const profile = await getUserProfileScoring();
    const next = buildInitialSuixinState({ bootId, profile });
    suixinStateRef.current = next;
    setSuixinBgColor(next.last_color || NEUTRAL_THEME_COLORS[1]);
    await setSuixinThemeState(next);
    return next;
  }, []);

  const advanceSuixinOnNextContent = useCallback(async () => {
    if (themeModeRef.current !== 'suixin') return;

    const bootId = getBootId();
    let current = suixinStateRef.current;
    if (!current) {
      current = await getSuixinThemeState();
    }

    // 冷启动后首次触发/或状态丢失：先初始化
    if (!current || current.boot_id !== bootId) {
      await ensureSuixinReady();
      return;
    }

    const next = advanceSuixinState(current);
    suixinStateRef.current = next;
    setSuixinBgColor(next.last_color || NEUTRAL_THEME_COLORS[1]);
    await setSuixinThemeState(next);
  }, [ensureSuixinReady]);

  // 动画相关 Shared Values
  const translateY = useSharedValue(0);
  const opacity = useSharedValue(1);
  const likeScale = useSharedValue(1);

  // 统一文案对象结构
  const currentFeed = useMemo(() => {
    const baseFeed =
      feedItems.length > 0
        ? feedItems
        : MOCK_CONTENT.map(item => ({
            content_id: item.id,
            text: t(item.textKey)
          }));

    if (!pendingPushItem) {
      return baseFeed;
    }

    return [
      pendingPushItem,
      ...baseFeed.filter((entry) => (
        String(entry.content_id) !== String(pendingPushItem.content_id) && entry.text !== pendingPushItem.text
      )),
    ];
  }, [feedItems, pendingPushItem, t]);
  useEffect(() => {
    currentFeedRef.current = currentFeed;
  }, [currentFeed]);

  const item = useMemo(() => {
    const data = currentFeed[index % currentFeed.length];
    return {
      id: String(data.content_id),
      text: data.text
    };
  }, [currentFeed, index]);

  // Home 文案：使用自主换行算法（Text Wrap 模块）
  // - 通过 onLayout 获取容器宽度
  // - 注入真实测量实现，确保“宽度派”评分与实际渲染一致
  useEffect(() => {
    let cancelled = false;

    // 未拿到宽度前先用原文（避免闪烁）
    if (!cardWidth || cardWidth <= 0) {
      if (__DEV__) {
        const key = `noWidth|${item.id}|${String(cardWidth)}`;
        if (wrapLogRef.current?.key !== key) {
          wrapLogRef.current = { key };
          console.log('[TextWrap][Home] cardWidth 未就绪，先回退原文', {
            itemId: item.id,
            lang: recoLang,
            cardWidth,
            themeMode,
          });
        }
      }
      setWrappedText(item.text);
      return () => {
        cancelled = true;
      };
    }

    const paddingHorizontal = themeMode === 'scenery' ? 50 : 30;
    const availableWidth = Math.max(0, Math.floor(cardWidth - paddingHorizontal * 2));

    const lang = recoLang === 'en' ? 'EN' : 'TC';

    const fontFamily =
      lang === 'EN'
        ? 'STIXTwoText'
        : Platform.select({
            ios: 'System',
            android: 'sans-serif',
            default: 'System',
          });

    const fontSpec = {
      fontSize: 24,
      fontWeight: lang === 'EN' ? '700' : '800',
      fontFamily: String(fontFamily ?? 'System'),
    };

    (async () => {
      try {
        if (__DEV__) {
          const key = `start|${item.id}|${lang}|${availableWidth}|${themeMode}`;
          if (wrapLogRef.current?.key !== key) {
            wrapLogRef.current = { key };
            console.log('[TextWrap][Home] wrapText 开始', {
              itemId: item.id,
              lang,
              themeMode,
              cardWidth,
              paddingHorizontal,
              availableWidth,
              fontSpec,
              textPreview: String(item.text ?? '').slice(0, 80),
              textLength: String(item.text ?? '').length,
            });
          }
        }

        const res = await wrapText({
          text: item.text,
          lang,
          context: 'APP',
          availableWidth,
          maxLines: 3,
          overflowMode: 'CLIP',
          lineMode: 'AUTO',
          // Home：采用“更偏好语气停顿/更好看”的排版风格微调（不影响算法默认 v1）
          configVersion: 'v1-home',
          debug: __DEV__,
          fontSpec,
          contextProfile: `APP|${Platform.OS}|home|${lang}`,
          measureWidthImpl: defaultMeasureWidthImpl,
          scoringOverrides:
            lang === 'TC'
              ? {
                  // 更偏好在逗号/句号等处断行（即便宽度允许也不一定要塞满）
                  weights: { R_PUNCT_BREAK: 180 },
                  // 让“理想行宽”更短，避免宽屏下过度延后断行
                  idealWidthRatio: { APP: 0.82 },
                  // 更宽容短行（尤其是第一行在标点处停顿）
                  minPreferredRatio: 0.45,
                  shortLastLineRatio: 0.45,
                }
              : undefined,
        });

        if (cancelled) return;
        if (__DEV__) {
          console.log('[TextWrap][Home] wrapText 成功', {
            itemId: item.id,
            wrappedText: res.wrappedText,
            linesCount: res.lines.length,
            meta: res.meta,
          });
        }
        setWrappedText(res.wrappedText);
      } catch (error) {
        // 任何异常都回退到原文，避免影响 Home 主流程
        if (__DEV__) {
          console.log('[TextWrap][Home] wrapText 异常，回退原文', {
            itemId: item.id,
            lang,
            availableWidth,
            fontSpec,
            errorName: (error as any)?.name,
            errorMessage: String((error as any)?.message ?? error),
            errorStack: (error as any)?.stack,
          });
        }
        if (cancelled) return;
        setWrappedText(item.text);
      }
    })();

    return () => {
      cancelled = true;
    };
  }, [item.text, cardWidth, recoLang, themeMode]);

  // 异步拉取新文案
  const fetchNewFeed = useCallback(async () => {
    if (isFetchingRef.current) return;
    isFetchingRef.current = true;
    setIsFetching(true);
    try {
      const scoringProfile = await getUserProfileScoring();
      if (!scoringProfile) return;

      const history = await getRecoFeedHistory();
      
      const { items, meta } = await fetchRecoFeed({
        k: 30,
        user_profile: scoringProfile,
        already_recommended_ids: history.already_recommended_ids,
        touched_or_viewed_ids: history.touched_or_viewed_ids,
      });

      if (items.length > 0) {
        const wasEmpty = feedItemsRef.current.length === 0;
        const newCache = {
          saved_at: new Date().toISOString(),
          lang: recoLang,
          items: items.map((x) => ({ content_id: x.content_id, text: x.text })),
          meta: meta as Record<string, unknown>,
        };
        await setRecoFeedCache(newCache);
        await recordRecoFeedServed(items.map((x) => x.content_id));
        setFeedItems(newCache.items.map((x) => ({ content_id: String(x.content_id), text: x.text })));
        // 如果当前是 mock 数据，切换到新数据的第一条
        if (wasEmpty) {
          setIndex(0);
        }
      }
    } catch (error) {
      console.error('Failed to fetch new feed:', error);
    } finally {
      isFetchingRef.current = false;
      setIsFetching(false);
    }
  }, [recoLang]);

  // 每次进入页面或页面获得焦点时刷新个人信息和缓存文案
  useFocusEffect(
    useCallback(() => {
      let cancelled = false;
      (async () => {
        const [mode, profile, cache, pendingMessage] = await Promise.all([
          getThemeMode(),
          getUserProfile(),
          getRecoFeedCache(),
          getPendingHomePushMessage(),
        ]);

        if (cancelled) return;
        setThemeModeState(mode);
        setProfileName(profile.name);
        if (pendingMessage?.text) {
          await applyPendingPushItem(pendingMessage);
          if (cancelled) return;
        }

        // 随心：若当前主题为随心，进入 Home 时确保状态就绪（仅冷启动会话重算）
        if (mode === 'suixin') {
          ensureSuixinReady().catch(() => {
            // ignore：失败时回退默认中性底色
            setSuixinBgColor(NEUTRAL_THEME_COLORS[1]);
          });
        }
        
        // 语言切换时：旧语言缓存不复用，触发重新拉取
        if (cache && cache.items.length > 0 && (cache.lang ?? 'en') === recoLang) {
          setFeedItems(cache.items.map((x) => ({ content_id: String(x.content_id), text: x.text })));
        } else {
          // 语言不匹配或没有缓存：先清空回落到本地 mock（会立即随语言切换），再拉取对应语言的推荐文案
          setFeedItems([]);
          setIndex(0);
          fetchNewFeed();
        }

        // Widget：前台辅助刷新（尽力而为）
        // - 写入 App Group 的 dailyReco 缓存
        // - 生成 wrapped_text_by_family，供 Widget 直接渲染
        ensureDailyWidgetRecoUpToDate({ reason: 'home_focus' }).catch(() => {});
      })();
      return () => {
        cancelled = true;
      };
    }, [applyPendingPushItem, fetchNewFeed, recoLang, ensureSuixinReady])
  );

  useEffect(() => {
    const unsubscribe = subscribeHomePushMessage((message) => {
      void applyPendingPushItem(message);
    });
    return unsubscribe;
  }, [applyPendingPushItem]);

  useEffect(() => {
    const sub = AppState.addEventListener('change', (state) => {
      if (state !== 'active') return;
      void consumePendingPushItem();
    });
    return () => sub.remove();
  }, [consumePendingPushItem]);

  const backgroundColor = useMemo(() => {
    if (themeMode === 'suixin') {
      return suixinBgColor;
    }
    if (themeMode === 'color') {
      const colorIndex = Math.floor(index / 10) % THEME_COLORS.length;
      return THEME_COLORS[colorIndex];
    }
    return '#F4D6C2'; // 风景模式下的默认底色（图片加载前显示）
  }, [themeMode, suixinBgColor, index]);

  // 计算当前应该显示的风景图索引（滑动 10 次切换一张）
  const natureImageIndex = useMemo(() => {
    return Math.floor(index / 10) % NATURE_IMAGES.length;
  }, [index]);

  const currentNatureImage = NATURE_IMAGES[natureImageIndex];

  const textAnimatedStyle = useAnimatedStyle(() => ({
    transform: [{ translateY: translateY.value }],
    opacity: opacity.value,
  }));

  const likeAnimatedStyle = useAnimatedStyle(() => ({
    transform: [{ scale: likeScale.value }],
  }));

  const setBusySafe = useCallback((next: boolean) => {
    busyRef.current = next;
    setBusy(next);
  }, []);

  const setLikeInFlight = useCallback((next: boolean) => {
    likeInFlightRef.current = next;
  }, []);

  const syncLikeFilledByIndex = useCallback((nextIndex: number) => {
    const list = currentFeedRef.current;
    const len = list.length;
    if (!len) {
      setLikeFilled(false);
      return;
    }
    const safe = ((nextIndex % len) + len) % len;
    const nextId = String(list[safe]?.content_id);
    setLikeFilled(likedIdsRef.current.has(nextId));
  }, []);

  const applyIndexChange = useCallback((nextIndex: number) => {
    indexRef.current = nextIndex;
    setIndex(nextIndex);
    syncLikeFilledByIndex(nextIndex);
  }, [syncLikeFilledByIndex]);

  const maybeFetchNewFeedIfNeeded = useCallback((nextIndex: number) => {
    const len = currentFeedRef.current.length;
    if (!len) return;
    // 当接近当前列表末尾时（例如还剩 5 条）提前拉取
    if (nextIndex + 5 >= len && !isFetchingRef.current) {
      fetchNewFeed();
    }
  }, [fetchNewFeed]);

  // 切换到下一条文案的统一动画逻辑
  const triggerNextContent = useCallback(() => {
    if (busyRef.current) return;
    setBusySafe(true);

    // 注意：不要在 Reanimated worklet 回调里读取 React ref（例如 indexRef/currentFeedRef），会导致值不更新或异常
    const nextIndex = indexRef.current + 1;

    // 1. 当前文案向上移动并消失
    translateY.value = withTiming(-40, { duration: 300, easing: Easing.out(Easing.quad) });
    opacity.value = withTiming(0, { duration: 300 }, (finished) => {
      if (finished) {
        // 2. 切换数据索引
        runOnJS(applyIndexChange)(nextIndex);
        runOnJS(advanceSuixinOnNextContent)();

        // 检查是否需要拉取新文案（注意：不要把匿名函数塞进 runOnJS，可能导致原生崩溃）
        runOnJS(maybeFetchNewFeedIfNeeded)(nextIndex);

        // 3. 准备下一条文案：先瞬移到下方 40pt
        translateY.value = 40;
        
        // 4. 下一条文案向上移动到原位并显现
        translateY.value = withTiming(0, { duration: 400, easing: Easing.out(Easing.back(1)) });
        opacity.value = withTiming(1, { duration: 400 }, (finished) => {
          if (finished) {
            runOnJS(setBusySafe)(false);
          }
        });
      }
    });
  }, [applyIndexChange, setBusySafe, translateY, opacity, advanceSuixinOnNextContent, maybeFetchNewFeedIfNeeded]);

  // 切换到上一条文案的统一动画逻辑（下滑触发）
  const triggerPrevContent = useCallback(() => {
    if (busyRef.current) return;
    setBusySafe(true);

    // 注意：同上，不要在 worklet 里读取 React ref
    const len = currentFeedRef.current.length;
    const raw = indexRef.current - 1;
    const nextIndex = len ? ((raw % len) + len) % len : Math.max(0, raw);

    // 1. 当前文案向下移动并消失
    translateY.value = withTiming(40, { duration: 300, easing: Easing.out(Easing.quad) });
    opacity.value = withTiming(0, { duration: 300 }, (finished) => {
      if (finished) {
        // 2. 切换数据索引（循环回退）
        runOnJS(applyIndexChange)(nextIndex);

        // 3. 准备上一条文案：先瞬移到上方 40pt
        translateY.value = -40;

        // 4. 上一条文案向下移动到原位并显现
        translateY.value = withTiming(0, { duration: 400, easing: Easing.out(Easing.back(1)) });
        opacity.value = withTiming(1, { duration: 400 }, (finished) => {
          if (finished) {
            runOnJS(setBusySafe)(false);
          }
        });
      }
    });
  }, [applyIndexChange, setBusySafe, translateY, opacity]);

  const lastTapRef = useRef<number>(0);
  
  // 使用 Ref 解决 PanResponder 闭包陷阱，确保手势回调能拿到最新的 state 和 function
  const handlersRef = useRef({ onPressLike, triggerNextContent, triggerPrevContent });
  useEffect(() => {
    handlersRef.current = { onPressLike, triggerNextContent, triggerPrevContent };
  }, [onPressLike, triggerNextContent, triggerPrevContent]);

  // 使用系统自带的 PanResponder 代替第三方手势库
  const panResponder = useRef(
    PanResponder.create({
      onStartShouldSetPanResponder: () => true, // 允许开始捕获
      onMoveShouldSetPanResponder: (_, gestureState) => {
        // 只有当垂直滑动距离大于 20 时才接管位移手势
        return Math.abs(gestureState.dy) > 20;
      },
      onPanResponderRelease: (_, gestureState) => {
        const now = Date.now();
        const DOUBLE_TAP_DELAY = 300;

        // 1. 双击逻辑判定
        if (now - lastTapRef.current < DOUBLE_TAP_DELAY) {
          // 判定为双击
          if (Math.abs(gestureState.dx) < 10 && Math.abs(gestureState.dy) < 10) {
            runOnJS(handlersRef.current.onPressLike)();
            lastTapRef.current = 0; // 重置
            return;
          }
        }
        lastTapRef.current = now;

        // 2. 上滑/下滑逻辑判定
        if (gestureState.dy < -50) { // 上滑超过 50pt
          runOnJS(handlersRef.current.triggerNextContent)();
        } else if (gestureState.dy > 50) { // 下滑超过 50pt
          runOnJS(handlersRef.current.triggerPrevContent)();
        }
      },
    })
  ).current;

  async function onPressLike() {
    if (busyRef.current) return;
    if (likeInFlightRef.current) return;

    // 已经喜欢过：不重复写入收藏，直接当作“下一条”
    if (likeFilled || likedIdsRef.current.has(item.id)) {
      triggerNextContent();
      return;
    }

    likeInFlightRef.current = true;

    const likedItemId = item.id;
    const likedItemText = item.text;
    // 先记下“已喜欢”，保证回退时能恢复点亮状态（即便异步保存稍后才完成）
    likedIdsRef.current.add(likedItemId);
    setLikeFilled(true);
    
    // 1. 获取当前日期
    const now = new Date();
    const dateStr = `${now.getFullYear()}.${String(now.getMonth() + 1).padStart(2, '0')}.${String(now.getDate()).padStart(2, '0')}`;

    // 2. 保存到收藏夹，包含当前背景信息
    const favItem = {
      favId: String(Date.now()), // 生成唯一 ID
      id: likedItemId,
      text: likedItemText,
      date: dateStr,
      themeMode: themeMode,
      background: themeMode === 'scenery' ? String(natureImageIndex) : backgroundColor,
    };
    console.log('Home: Triggering addFavorite', JSON.stringify(favItem));
    try {
      await addFavorite(favItem);
    } catch (error) {
      console.error('Home: addFavorite 失败', error);
    }

    // 3. 记录到后端 Reaction（喜欢）
    console.log('Home: Triggering setReaction', item.id);
    try {
      await setReaction(item.id, 'like');
    } catch (error) {
      console.error('Home: setReaction 失败', error);
    }

    // 4. 爱心缩放动画
    likeScale.value = withSequence(
      withTiming(0.8, { duration: 100 }),
      withTiming(1.2, { duration: 150 }),
      withTiming(1, { duration: 100 }, (finished) => {
        runOnJS(setLikeInFlight)(false);
        if (finished) {
          console.log('Home: Like animation finished, triggering next content');
          runOnJS(triggerNextContent)();
        }
      })
    );
  }

  async function onSelectTheme(next: ThemeMode) {
    setThemeModeState(next);
    await setThemeMode(next);
    setThemeOpen(false);

    // 切换到随心：不主动重算（除非冷启动会话变化/状态不存在），仅确保可用
    if (next === 'suixin') {
      await ensureSuixinReady().catch(() => {
        setSuixinBgColor(NEUTRAL_THEME_COLORS[1]);
      });
    }
  }

  const actionsBottom = isTablet
    ? Math.max(insets.bottom + 36, Math.min(windowHeight * 0.12, 140))
    : windowHeight * 0.16;

  return (
    <View style={[styles.container, { backgroundColor }]} {...panResponder.panHandlers}>
      {themeMode === 'scenery' && (
        <ImageBackground
          source={currentNatureImage}
          style={StyleSheet.absoluteFill}
          resizeMode="cover"
        />
      )}

      {/* 自绘顶部按钮：不使用系统 Header，彻底避免 iOS 导航栏的毛玻璃/液玻璃材质 */}
      <View
        style={[
          styles.topRight,
          {
            top: insets.top + (isTablet ? 16 : 8),
            right: isTablet ? 26 : 20,
          },
        ]}
      >
        <CircleIconButton
          onPress={() => setThemeOpen(true)}
          accessibilityLabel={t('home.theme')}
        >
          <ThemeIcon width={20} height={20} />
        </CircleIconButton>
        <CircleIconButton
          onPress={() => setProfileOpen(true)}
          accessibilityLabel={t('home.profile')}
        >
          <MyIcon width={20} height={20} />
        </CircleIconButton>
      </View>

      <Animated.View style={[styles.card, textAnimatedStyle, themeMode === 'scenery' && styles.sceneryCard]}>
        <View
          style={[styles.textMeasureBox, isTablet && styles.textMeasureBoxTablet]}
          onLayout={(e) => {
            const w = e.nativeEvent.layout.width;
            if (Number.isFinite(w) && w > 0) setCardWidth(w);
          }}
        >
          <Text style={[styles.text, isEnglish && styles.textEnglish, themeMode === 'scenery' && styles.sceneryText]}>
            {wrappedText || item.text}
          </Text>
        </View>
      </Animated.View>

      <View style={[styles.actions, { bottom: actionsBottom }]}>
        <Animated.View style={[styles.reactionButton, likeAnimatedStyle]}>
          <Pressable
            onPress={onPressLike}
            accessibilityRole="button"
            accessibilityLabel={t('home.like')}
            // 稍微增大可点击区域，提升单手操作成功率
            hitSlop={24}
            style={styles.reactionInner}
          >
            {likeFilled ? (
              <LikeFilledIcon width={40} height={41} color="#EA6969" />
            ) : (
              <LikeIcon 
                width={40} 
                height={41} 
                color={themeMode === 'scenery' ? '#FFFFFF' : '#5E2A28'}
              />
            )}
          </Pressable>
        </Animated.View>
      </View>

      <ThemeModal visible={themeOpen} mode={themeMode} onSelect={onSelectTheme} onClose={() => setThemeOpen(false)} />
      <ProfileModal
        visible={profileOpen}
        name={profileName}
        onClose={() => setProfileOpen(false)}
      />
    </View>
  );
}

function CircleIconButton({
  onPress,
  accessibilityLabel,
  children,
}: {
  onPress: () => void;
  accessibilityLabel: string;
  children: React.ReactNode;
}) {
  return (
    <Pressable
      onPress={onPress}
      // 稍微增大可点击区域，提升易用性
      hitSlop={14}
      accessibilityRole="button"
      accessibilityLabel={accessibilityLabel}
      style={styles.circleBtn}
    >
      {children}
    </Pressable>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    justifyContent: 'center',
    alignItems: 'center',
  },
  topRight: {
    position: 'absolute',
    flexDirection: 'row',
    gap: 10,
    zIndex: 30,
  },
  circleBtn: {
    width: 40,
    height: 40,
    borderRadius: 20,
    backgroundColor: 'rgba(255,255,255,0.75)',
    alignItems: 'center',
    justifyContent: 'center',
  },
  card: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    justifyContent: 'center',
    alignItems: 'center',
    paddingHorizontal: 30,
    zIndex: 5, // 降低层级，防止遮挡底部按钮
  },
  text: {
    fontSize: 24,
    lineHeight: 34,
    color: '#5E2A28',
    fontWeight: '800',
    textAlign: 'center',
  },
  textMeasureBox: {
    width: '100%',
    alignItems: 'center',
  },
  textMeasureBoxTablet: {
    maxWidth: 760,
  },
  textEnglish: {
    fontFamily: 'STIXTwoText',
    // 英文字体保持较粗但避免过度发黑
    fontWeight: '700',
  },
  sceneryCard: {
    // 风景模式下稍微收窄文案宽度，增加呼吸感
    paddingHorizontal: 50,
  },
  sceneryText: {
    color: '#FFFFFF',
    textShadowColor: 'rgba(0, 0, 0, 0.5)',
    textShadowOffset: { width: 0, height: 1 },
    textShadowRadius: 4,
  },
  actions: {
    position: 'absolute',
    left: 0,
    right: 0,
    flexDirection: 'row',
    justifyContent: 'center',
    zIndex: 20, // 提升层级，确保在最顶层可点击
  },
  reactionButton: {
    alignItems: 'center',
    justifyContent: 'center',
  },
  reactionInner: {
    alignItems: 'center',
    justifyContent: 'center',
  },
});
