import ActivityHeatMap from '@/components/ActivityHeatMap';
import { BadgeShowcaseModal } from '@/components/badges/BadgeShowcaseModal';
import { PRIVACY_POLICY_URL, USER_AGREEMENT_URL } from '@/constants/Agree';
import { palette } from '@/constants/Colors';
import { ROUTES } from '@/constants/Routes';
import { getTabBarBottomPadding } from '@/constants/TabBar';
import { useMembershipModal } from '@/contexts/MembershipModalContext';
import { useAppDispatch, useAppSelector } from '@/hooks/redux';
import { useAuthGuard } from '@/hooks/useAuthGuard';
import type { BadgeDto } from '@/services/badges';
import { reportBadgeShowcaseDisplayed } from '@/services/badges';
import { updateUser, type UserLanguage } from '@/services/users';
import { fetchAvailableBadges, selectBadgeCounts, selectBadgePreview, selectSortedBadges } from '@/store/badgesSlice';
import { selectActiveMembershipPlanName } from '@/store/membershipSlice';
import { DEFAULT_MEMBER_NAME, fetchActivityHistory, fetchMyProfile } from '@/store/userSlice';
import { getItem, setItem } from '@/utils/kvStore';
import { log } from '@/utils/logger';
import { Ionicons } from '@expo/vector-icons';
import { useFocusEffect } from '@react-navigation/native';
import dayjs from 'dayjs';
import { GlassView, isLiquidGlassAvailable } from 'expo-glass-effect';
import { Image } from 'expo-image';
import { LinearGradient } from 'expo-linear-gradient';
import { useRouter } from 'expo-router';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Linking, Modal, RefreshControl, ScrollView, StatusBar, StyleSheet, Switch, Text, TouchableOpacity, TouchableWithoutFeedback, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

import { AppLanguage, changeAppLanguage, getNormalizedLanguage } from '@/i18n';

const DEFAULT_AVATAR_URL = 'https://plates-1251306435.cos.ap-guangzhou.myqcloud.com/images/seal-avatar/2.jpeg';

type MenuItem = {
  icon: React.ComponentProps<typeof Ionicons>['name'];
  title: string;
  onPress?: () => void;
  type?: 'switch';
  switchValue?: boolean;
  onSwitchChange?: (value: boolean) => void;
  isDanger?: boolean;
  rightText?: string;
};

type MenuSectionConfig = {
  title: string;
  items: MenuItem[];
};

type LanguageOption = {
  code: AppLanguage;
  label: string;
  description: string;
};

export default function PersonalScreen() {
  const dispatch = useAppDispatch();
  const { confirmLogout, confirmDeleteAccount, isLoggedIn, pushIfAuthedElseLogin, ensureLoggedIn } = useAuthGuard();
  const { openMembershipModal } = useMembershipModal();
  const insets = useSafeAreaInsets();
  const { t, i18n } = useTranslation();
  const router = useRouter();
  

  const isLgAvaliable = isLiquidGlassAvailable();
  const [languageModalVisible, setLanguageModalVisible] = useState(false);
  const [isSwitchingLanguage, setIsSwitchingLanguage] = useState(false);
  const [refreshing, setRefreshing] = useState(false);

  const languageOptions = useMemo<LanguageOption[]>(() => ([
    {
      code: 'zh' as AppLanguage,
      label: t('personal.language.options.zh.label'),
      description: t('personal.language.options.zh.description'),
    },
    {
      code: 'en' as AppLanguage,
      label: t('personal.language.options.en.label'),
      description: t('personal.language.options.en.description'),
    },
  ]), [t]);

  const activeLanguageCode = getNormalizedLanguage(i18n.language);
  const activeLanguageLabel = languageOptions.find((option) => option.code === activeLanguageCode)?.label || '';

  const handleLanguageSelect = useCallback(async (language: AppLanguage) => {
    setLanguageModalVisible(false);
    if (language === activeLanguageCode || isSwitchingLanguage) {
      return;
    }
    try {
      setIsSwitchingLanguage(true);
      
      // 将 AppLanguage ('zh' | 'en') 映射到 UserLanguage ('zh-CN' | 'en-US')
      const languageMap: Record<AppLanguage, UserLanguage> = {
        'zh': 'zh-CN',
        'en': 'en-US',
      };
      const userLanguage = languageMap[language];
      
      // 先切换本地语言
      await changeAppLanguage(language);
      
      // 如果用户已登录，同步更新服务器语言设置
      if (isLoggedIn) {
        try {
          await updateUser({ language: userLanguage });
          log.info('语言设置已同步到服务器', { language: userLanguage });
        } catch (error) {
          log.warn('同步语言设置到服务器失败', error);
          // 服务器更新失败不影响本地语言切换，静默处理
        }
      }
    } catch (error) {
      log.warn('语言切换失败', error);
    } finally {
      setIsSwitchingLanguage(false);
    }
  }, [activeLanguageCode, isSwitchingLanguage, isLoggedIn]);

  // 推送通知设置仅在独立页面管理

  // 开发者模式相关状态
  const [showDeveloperSection, setShowDeveloperSection] = useState(false);
  const clickTimestamps = useRef<number[]>([]);
  const clickTimeoutRef = useRef<number | null>(null);

  const handleMembershipPress = useCallback(async () => {
    const ok = await ensureLoggedIn();
    if (!ok) {
      return;
    }
    openMembershipModal();
  }, [ensureLoggedIn, openMembershipModal]);

  const handleBadgesPress = useCallback(() => {
    router.push(ROUTES.BADGES);
  }, [router]);

  // 计算底部间距
  const bottomPadding = useMemo(() => {
    return getTabBarBottomPadding(60) + (insets?.bottom ?? 0);
  }, [insets?.bottom]);

  // 直接使用 Redux 中的用户信息，避免重复状态管理
  const userProfile = useAppSelector((state) => state.user.profile);
  const activeMembershipPlanName = useAppSelector(selectActiveMembershipPlanName);
  const badgePreview = useAppSelector(selectBadgePreview);
  const badgeCounts = useAppSelector(selectBadgeCounts);
  const sortedBadges = useAppSelector(selectSortedBadges);

  const [showcaseBadge, setShowcaseBadge] = useState<BadgeDto | null>(null);
  const autoShownBadgeCodes = useRef<Set<string>>(new Set());

  const openBadgeShowcase = useCallback((badge: BadgeDto) => {
    autoShownBadgeCodes.current.add(badge.code);
    setShowcaseBadge(badge);
  }, []);

  useEffect(() => {
    if (showcaseBadge) {
      return;
    }

    const nextBadgeToShow = sortedBadges.find(
      (badge) => badge.isAwarded && badge.isShow === false && !autoShownBadgeCodes.current.has(badge.code)
    );

    if (nextBadgeToShow) {
      openBadgeShowcase(nextBadgeToShow);
    }
  }, [openBadgeShowcase, showcaseBadge, sortedBadges]);

  const handleBadgeShowcaseClose = useCallback(async () => {
    if (!showcaseBadge) {
      return;
    }

    const badgeCode = showcaseBadge.code;
    setShowcaseBadge(null);

    try {
      await reportBadgeShowcaseDisplayed(badgeCode);
    } catch (error) {
      log.warn('report-badge-showcase-failed', error);
    }
  }, [showcaseBadge]);




  // 首次加载时获取用户信息和数据
  useEffect(() => {
    dispatch(fetchAvailableBadges());

    if (!isLoggedIn) return;

    dispatch(fetchMyProfile());
    dispatch(fetchActivityHistory());
  }, [dispatch, isLoggedIn]);

  // 页面聚焦时智能刷新（依赖 Redux 的缓存策略）
  useFocusEffect(
    useCallback(() => {
      // 徽章数据由 Redux 的缓存策略控制，只有过期才会重新请求
      dispatch(fetchAvailableBadges());
    }, [dispatch, isLoggedIn])
  );

  // 手动刷新处理
  const onRefresh = useCallback(async () => {
    setRefreshing(true);
    try {
      // 并行刷新所有数据
      await Promise.all([
        dispatch(fetchMyProfile()).unwrap(),
        dispatch(fetchActivityHistory()).unwrap(),
        dispatch(fetchAvailableBadges()).unwrap(),
      ]);
    } catch (error) {
      log.warn('刷新数据失败', error);
    } finally {
      setRefreshing(false);
    }
  }, [dispatch]);

  // 移除 loadNotificationPreference 函数，因为已移到通知设置页面

  // 加载开发者模式状态
  const loadDeveloperModeState = async () => {
    try {
      const enabled = await getItem('developer_mode_enabled');
      if (enabled === 'true') {
        setShowDeveloperSection(true);
      }
    } catch (error) {
      console.error('加载开发者模式状态失败:', error);
    }
  };

  // 保存开发者模式状态
  const saveDeveloperModeState = async (enabled: boolean) => {
    try {
      await setItem('developer_mode_enabled', enabled.toString());
    } catch (error) {
      console.error('保存开发者模式状态失败:', error);
    }
  };

  // 数据格式化函数
  const formatHeight = () => {
    if (userProfile.height == null) return '--';
    return `${parseFloat(userProfile.height).toFixed(1)}cm`;
  };

  const formatWeight = () => {
    if (userProfile.weight == null) return '--';
    return `${parseFloat(userProfile.weight).toFixed(1)}kg`;
  };

  const formatAge = () => {
    if (!userProfile.birthDate) return '--';
    const birthDate = new Date(userProfile.birthDate);
    const today = new Date();
    const age = today.getFullYear() - birthDate.getFullYear();
    return `${age}${t('personal.stats.ageSuffix')}`;
  };

  // 显示名称
  const displayName = (userProfile.name?.trim()) ? userProfile.name : DEFAULT_MEMBER_NAME;
  const profileActionLabel = isLoggedIn ? t('personal.edit') : t('personal.login');
  const aiUsageValue = userProfile.isVip ? t('personal.aiUsageUnlimited') : userProfile.freeUsageCount ?? 0;

  // 初始化时只加载开发者模式状态
  useEffect(() => {
    loadDeveloperModeState();
  }, []);

  // 处理用户名连续点击
  const handleUserNamePress = () => {
    const now = Date.now();
    clickTimestamps.current.push(now);

    // 清除之前的超时
    if (clickTimeoutRef.current) {
      clearTimeout(clickTimeoutRef.current);
    }

    // 只保留最近1秒内的点击
    clickTimestamps.current = clickTimestamps.current.filter(timestamp => now - timestamp <= 1000);

    // 检查是否有3次连续点击
    if (clickTimestamps.current.length >= 3) {
      setShowDeveloperSection(true);
      saveDeveloperModeState(true); // 持久化保存开发者模式状态
      clickTimestamps.current = []; // 清空点击记录
      log.info('开发者模式已激活');
    } else {
      // 1秒后清空点击记录
      clickTimeoutRef.current = setTimeout(() => {
        clickTimestamps.current = [];
      }, 1000);
    }
  };

  // 移除 handleNotificationToggle 函数，因为已移到通知设置页面

  // 用户信息头部
  const UserHeader = () => (
    <View style={[styles.sectionContainer, {
      marginBottom: 0
    }]}>

      <View style={[styles.userInfoContainer,]}>
        <View style={styles.avatarContainer}>
          <Image
            source={userProfile.avatar || DEFAULT_AVATAR_URL}
            style={styles.avatar}
            contentFit="cover"
            transition={200}
            cachePolicy="memory-disk"
          />
        </View>
        <View style={styles.userDetails}>
          <TouchableOpacity onPress={handleUserNamePress} activeOpacity={0.7}>
            <Text style={styles.userName}>{displayName}</Text>
          </TouchableOpacity>
          {userProfile.memberNumber && String(userProfile.memberNumber).trim().length > 0 ? (
            <Text style={styles.userMemberNumber}>
              {t('personal.memberNumber', { number: userProfile.memberNumber })}
            </Text>
          ) : null}
          {userProfile.freeUsageCount !== undefined && (
            <View style={styles.aiUsageContainer}>
              <Ionicons name="sparkles-outline" as any size={12} color="#9370DB" />
              <Text style={styles.aiUsageText}>
                {t('personal.aiUsage', { value: aiUsageValue })}
              </Text>
            </View>
          )}
        </View>
        {isLgAvaliable ? (
          <TouchableOpacity onPress={() => pushIfAuthedElseLogin('/profile/edit')}>
            <GlassView style={styles.editButtonGlass} isInteractive>
              <Text style={styles.editButtonTextGlass}>{profileActionLabel}</Text>
            </GlassView>
          </TouchableOpacity>
        ) : (
          <TouchableOpacity style={styles.editButton} onPress={() => pushIfAuthedElseLogin('/profile/edit')}>
            <Text style={styles.editButtonText}>{profileActionLabel}</Text>
          </TouchableOpacity>
        )}

      </View>

    </View>
  );

  const MembershipBanner = () => (
    <View style={styles.sectionContainer}>
      <TouchableOpacity
        activeOpacity={0.9}
        onPress={() => {
          void handleMembershipPress();
        }}
      >
        <Image
          source={{ uri: 'https://plates-1251306435.cos.ap-guangzhou.myqcloud.com/images/banner/vip2.png' }}
          style={styles.membershipBannerImage}
          contentFit="cover"
          transition={200}
          cachePolicy="memory-disk"
        />
      </TouchableOpacity>
    </View>
  );

  const VipMembershipCard = () => {
    const fallbackProfile = userProfile as Record<string, unknown>;
    const fallbackExpire = ['membershipExpiration', 'vipExpiredAt', 'vipExpiresAt', 'vipExpireDate']
      .map((key) => fallbackProfile[key])
      .find((value): value is string => typeof value === 'string' && value.trim().length > 0);

    const rawExpireDate = userProfile.membershipExpiration ?? fallbackExpire;

    let formattedExpire = t('personal.membership.validForever');
    if (typeof rawExpireDate === 'string' && rawExpireDate.trim().length > 0) {
      const parsed = dayjs(rawExpireDate);
      formattedExpire = parsed.isValid() ? parsed.format(t('personal.membership.dateFormat')) : rawExpireDate;
    }

    const planName =
      (activeMembershipPlanName && activeMembershipPlanName.trim()) ||
      (userProfile.vipPlanName && userProfile.vipPlanName.trim()) ||
      t('personal.membership.planFallback');

    return (
      <View style={styles.sectionContainer}>
        <LinearGradient
          colors={['#5B4CFF', '#8D5BEA']}
          start={{ x: 0, y: 0 }}
          end={{ x: 1, y: 1 }}
          style={styles.vipCard}
        >
          <View style={styles.vipCardDecorationLarge} />
          <View style={styles.vipCardDecorationSmall} />
          <View style={styles.vipCardHeader}>
            <View style={styles.vipCardHeaderLeft}>
              <View style={styles.vipBadge}>
                <Ionicons name="sparkles-outline" as any size={16} color="#FFD361" />
                <Text style={styles.vipBadgeText}>{t('personal.membership.badge')}</Text>
              </View>
              <Text style={styles.vipCardTitle}>{planName}</Text>
            </View>
            <View style={styles.vipCardIllustration}>
              <Ionicons name="ribbon" as any size={32} color="rgba(255,255,255,0.88)" />
            </View>
          </View>

          <View style={styles.vipCardFooter}>
            <View style={styles.vipExpiryInfo}>
              <Text style={styles.vipExpiryLabel}>{t('personal.membership.expiryLabel')}</Text>
              <View style={styles.vipExpiryRow}>
                <Ionicons name="time-outline" as any size={16} color="rgba(255,255,255,0.85)" />
                <Text style={styles.vipExpiryValue}>{formattedExpire}</Text>
              </View>
            </View>
            <TouchableOpacity
              style={styles.vipChangeButton}
              activeOpacity={0.85}
              onPress={() => {
                void handleMembershipPress();
              }}
            >
              <Ionicons name="swap-horizontal-outline" as any size={16} color="#2F1767" />
              <Text style={styles.vipChangeButtonText}>{t('personal.membership.changeButton')}</Text>
            </TouchableOpacity>
          </View>
        </LinearGradient>
      </View>
    );
  };

  // 数据统计部分
  const StatsSection = () => (
    <View style={styles.sectionContainer}>
      <View style={[styles.cardContainer, {
        backgroundColor: 'transparent'
      }]}>
        <View style={styles.statsContainer}>
          <View style={styles.statItem}>
            <Text style={styles.statValue}>{formatHeight()}</Text>
            <Text style={styles.statLabel}>{t('personal.stats.height')}</Text>
          </View>
          <View style={styles.statItem}>
            <Text style={styles.statValue}>{formatWeight()}</Text>
            <Text style={styles.statLabel}>{t('personal.stats.weight')}</Text>
          </View>
          <View style={styles.statItem}>
            <Text style={styles.statValue}>{formatAge()}</Text>
            <Text style={styles.statLabel}>{t('personal.stats.age')}</Text>
          </View>
        </View>
      </View>
    </View>
  );

  // 优化性能：使用 useMemo 缓存计算结果，避免每次渲染都重新计算
  const BadgesPreviewSection = React.memo(() => {
    // 使用 useMemo 缓存切片和计算结果，只有当 badgePreview 或 badgeCounts 变化时才重新计算
    const { previewBadges, hasBadges, extraCount } = useMemo(() => {
      const previewBadges = badgePreview.slice(0, 3);
      const hasBadges = previewBadges.length > 0;
      const extraCount = Math.max(0, badgeCounts.total - previewBadges.length);
      return { previewBadges, hasBadges, extraCount };
    }, [badgePreview, badgeCounts]);

    // 使用 useMemo 缓存标题文本，避免每次渲染都调用 t() 函数
    const titleText = useMemo(() => t('personal.badgesPreview.title'), [t]);
    const emptyText = useMemo(() => t('personal.badgesPreview.empty'), [t]);

    return (
      <View style={styles.sectionContainer}>
        <TouchableOpacity style={[styles.cardContainer, styles.badgesRowCard]} onPress={handleBadgesPress} activeOpacity={0.85}>
          <Text style={styles.badgesRowTitle}>{titleText}</Text>
          {hasBadges ? (
            <View style={styles.badgesRowContent}>
              <View style={styles.badgesStack}>
                {previewBadges.map((badge, index) => (
                  <BadgeCompactItem
                    key={badge.code}
                    badge={badge}
                    index={index}
                    totalBadges={previewBadges.length}
                  />
                ))}
              </View>
              {extraCount > 0 && (
                <View style={[styles.badgeCompactBubble, styles.badgeExtraBubble, styles.badgeExtraBubbleInline]}>
                  <Text style={styles.badgeExtraText}>+{extraCount}</Text>
                </View>
              )}
            </View>
          ) : (
            <Text style={styles.badgesRowEmpty}>{emptyText}</Text>
          )}
        </TouchableOpacity>
      </View>
    );
  });

  // 将徽章项提取为独立的 memo 组件，减少重复渲染
  const BadgeCompactItem = React.memo(({ badge, index, totalBadges }: {
    badge: BadgeDto;
    index: number;
    totalBadges: number;
  }) => {
    // 使用 useMemo 缓存样式计算，避免每次渲染都重新计算
    const badgeStyle = useMemo(() => [
      styles.badgeCompactBubble,
      badge.isAwarded ? styles.badgeCompactBubbleEarned : styles.badgeCompactBubbleLocked,
      {
        marginLeft: index === 0 ? 0 : -12,
        zIndex: totalBadges - index,
      },
    ], [badge.isAwarded, index, totalBadges]);

    // 使用 useMemo 缓存图标文本，避免每次渲染都重新计算
    const iconText = useMemo(() =>
      (badge.icon && String(badge.icon).trim()) || '🏅',
      [badge.icon]
    );

    return (
      <View style={badgeStyle}>
        {badge.imageUrl ? (
          <Image
            source={{ uri: badge.imageUrl }}
            style={styles.badgeCompactImage}
            contentFit="cover"
            transition={200}
            cachePolicy="memory-disk"
          />
        ) : (
          <View style={styles.badgeCompactFallback}>
            <Text style={styles.badgeCompactFallbackText}>
              {iconText}
            </Text>
          </View>
        )}
        {!badge.isAwarded && (
          <View style={styles.badgeCompactOverlay}>
            <Ionicons name="lock-closed" as any size={16} color="#FFFFFF" />
          </View>
        )}
      </View>
    );
  });

  // 菜单项组件
  const MenuSection = ({ title, items }: { title: string; items: MenuItem[] }) => (
    <View style={styles.sectionContainer}>
      <Text style={styles.sectionTitle}>{title}</Text>
      <View style={styles.cardContainer}>
        {items.map((item, index) => (
          <TouchableOpacity
            key={index}
            style={[styles.menuItem, index === items.length - 1 && { borderBottomWidth: 0 }]}
            onPress={item.type === 'switch' ? undefined : item.onPress}
            disabled={item.type === 'switch'}
          >
            <View style={styles.menuItemLeft}>
              <View style={[
                styles.iconContainer,
              ]}>
                <Ionicons
                  name={item.icon}
                  size={20}
                  color={item.isDanger ? '#FF4444' : '#9370DB'}
                />
              </View>
              <Text style={styles.menuItemText}>{item.title}</Text>
            </View>
            {item.type === 'switch' ? (
              <Switch
                value={item.switchValue || false}
                onValueChange={item.onSwitchChange || (() => { })}
                trackColor={{ false: '#E5E5E5', true: '#9370DB' }}
                thumbColor="#FFFFFF"
                style={styles.switch}
              />
            ) : (
              <View style={styles.menuRight}>
                {item.rightText && String(item.rightText).trim() ? (
                  <Text style={styles.menuRightText}>{item.rightText}</Text>
                ) : null}
                <Ionicons name="chevron-forward" as any size={20} color="#CCCCCC" />
              </View>
            )}
          </TouchableOpacity>
        ))}
      </View>
    </View>
  );

  // 菜单项配置
  const menuSections: MenuSectionConfig[] = [
    {
      title: t('personal.sections.healthData'),
      items: [
        {
          icon: 'medkit-outline' as React.ComponentProps<typeof Ionicons>['name'],
          title: t('personal.menu.healthDataPermissions'),
          onPress: () => router.push(ROUTES.HEALTH_DATA_PERMISSIONS),
        },
      ],
    },
    {
      title: t('personal.sections.notifications'),
      items: [
        {
          icon: 'notifications-outline' as React.ComponentProps<typeof Ionicons>['name'],
          title: t('personal.menu.notificationSettings'),
          onPress: () => pushIfAuthedElseLogin(ROUTES.NOTIFICATION_SETTINGS),
        },
      ],
    },
    {
      title: t('personal.sections.medicalSources'),
      items: [
        {
          icon: 'medkit-outline' as React.ComponentProps<typeof Ionicons>['name'],
          title: t('personal.menu.whoSource'),
          onPress: () => Linking.openURL('https://www.who.int'),
        },
      ],
    },
    {
      title: t('personal.language.title'),
      items: [
        {
          icon: 'language-outline' as React.ComponentProps<typeof Ionicons>['name'],
          title: t('personal.language.menuTitle'),
          onPress: () => setLanguageModalVisible(true),
          rightText: activeLanguageLabel || '',
        },
      ],
    },
    {
      title: t('personal.sections.customization'),
      items: [
        {
          icon: 'albums-outline' as React.ComponentProps<typeof Ionicons>['name'],
          title: t('personal.menu.tabBarConfig'),
          onPress: () => router.push(ROUTES.TAB_BAR_CONFIG),
        },
      ],
    },
    // 开发者section（需要连续点击三次用户名激活）
    ...(showDeveloperSection ? [{
      title: t('personal.sections.developer'),
      items: [
        {
          icon: 'code-slash-outline' as React.ComponentProps<typeof Ionicons>['name'],
          title: t('personal.menu.developerOptions'),
          onPress: () => pushIfAuthedElseLogin(ROUTES.DEVELOPER),
        },
        {
          icon: 'settings-outline' as React.ComponentProps<typeof Ionicons>['name'],
          title: t('personal.menu.pushSettings'),
          onPress: () => pushIfAuthedElseLogin(ROUTES.PUSH_NOTIFICATION_SETTINGS),
        },
      ],
    }] : []),
    {
      title: t('personal.sections.other'),
      items: [
        {
          icon: 'shield-checkmark-outline' as React.ComponentProps<typeof Ionicons>['name'],
          title: t('personal.menu.privacyPolicy'),
          onPress: () => Linking.openURL(PRIVACY_POLICY_URL),
        },
        {
          icon: 'chatbubble-ellipses-outline' as React.ComponentProps<typeof Ionicons>['name'],
          title: t('personal.menu.feedback'),
          onPress: () => Linking.openURL('mailto:richardwei1995@gmail.com'),
        },
        {
          icon: 'document-text-outline' as React.ComponentProps<typeof Ionicons>['name'],
          title: t('personal.menu.userAgreement'),
          onPress: () => Linking.openURL(USER_AGREEMENT_URL),
        },
      ],
    },
    // 只有登录用户才显示账号与安全菜单
    ...(isLoggedIn ? [{
      title: t('personal.sections.account'),
      items: [
        {
          icon: 'log-out-outline' as React.ComponentProps<typeof Ionicons>['name'],
          title: t('personal.menu.logout'),
          onPress: confirmLogout,
          isDanger: false,
        },
        {
          icon: 'trash-outline' as React.ComponentProps<typeof Ionicons>['name'],
          title: t('personal.menu.deleteAccount'),
          onPress: confirmDeleteAccount,
          isDanger: true,
        },
      ],
    }] : []),
  ];

  const LanguageSelectorModal = () => (
    <Modal
      animationType="fade"
      transparent
      visible={languageModalVisible}
      onRequestClose={() => setLanguageModalVisible(false)}
    >
      <View style={styles.languageModalOverlay}>
        <TouchableWithoutFeedback onPress={() => setLanguageModalVisible(false)}>
          <View style={styles.languageModalBackdrop} />
        </TouchableWithoutFeedback>
        <View style={styles.languageModalContent}>
          <Text style={styles.languageModalTitle}>{t('personal.language.modalTitle')}</Text>
          <Text style={styles.languageModalSubtitle}>{t('personal.language.modalSubtitle')}</Text>
          {languageOptions.map((option) => {
            const isSelected = option.code === activeLanguageCode;
            return (
              <TouchableOpacity
                key={option.code}
                activeOpacity={0.85}
                style={[
                  styles.languageOption,
                  isSelected && styles.languageOptionSelected,
                  isSwitchingLanguage && styles.languageOptionDisabled,
                ]}
                onPress={() => handleLanguageSelect(option.code)}
                disabled={isSwitchingLanguage}
              >
                <View style={styles.languageOptionTextGroup}>
                  <Text style={styles.languageOptionLabel}>
                    {(option.label && String(option.label).trim()) || ''}
                  </Text>
                  <Text style={styles.languageOptionDescription}>
                    {(option.description && String(option.description).trim()) || ''}
                  </Text>
                </View>
                {isSelected && (
                  <Ionicons name="checkmark-circle" as any size={20} color="#9370DB" />
                )}
              </TouchableOpacity>
            );
          })}
          <TouchableOpacity
            style={styles.languageModalClose}
            onPress={() => setLanguageModalVisible(false)}
            activeOpacity={0.8}
          >
            <Text style={styles.languageModalCloseText}>{t('personal.language.cancel')}</Text>
          </TouchableOpacity>
        </View>
      </View>
    </Modal>
  );

  return (
    <View style={styles.container}>
      <StatusBar barStyle={'dark-content'} backgroundColor="transparent" translucent />

      {/* 背景渐变 */}
      <LinearGradient
        colors={[palette.purple[100], '#F5F5F5']}
        start={{ x: 1, y: 0 }}
        end={{ x: 0.3, y: 0.4 }}
        style={styles.gradientBackground}
      />

      <ScrollView
        style={styles.scrollView}
        contentContainerStyle={{
          paddingTop: insets.top,
          paddingBottom: bottomPadding,
          paddingHorizontal: 16,
        }}
        showsVerticalScrollIndicator={false}
        refreshControl={
          <RefreshControl
            refreshing={refreshing}
            onRefresh={onRefresh}
            tintColor="#9370DB"
            colors={['#9370DB']}
            progressViewOffset={insets.top}
          />
        }
      >
        <UserHeader />
        {userProfile.isVip ? <VipMembershipCard /> : <MembershipBanner />}
        <StatsSection />
        <BadgesPreviewSection />
        <View style={styles.fishRecordContainer}>
          {/* <Image
              source={{ uri: 'https://plates-1251306435.cos.ap-guangzhou.myqcloud.com/images/icons/icon-profile-fish.png' }}
              contentFit="cover"
              style={{ width: 16, height: 16, marginLeft: 6 }}
              transition={200}
              cachePolicy="memory-disk"
            /> */}
          <Text style={styles.fishRecordText}>{t('personal.fishRecord')}</Text>
        </View>
        <ActivityHeatMap />
        {menuSections.map((section, index) => (
          <MenuSection key={index} title={section.title} items={section.items} />
        ))}
      </ScrollView>
      <BadgeShowcaseModal
        badge={showcaseBadge}
        onClose={handleBadgeShowcaseClose}
        username={displayName}
        appName="Out Live"
      />
      <LanguageSelectorModal />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F5F5F5',
  },
  gradientBackground: {
    position: 'absolute',
    left: 0,
    right: 0,
    top: 0,
    height: '60%',
  },
  scrollView: {
    flex: 1,
  },
  // 部分容器
  sectionContainer: {
    marginBottom: 20,
  },
  sectionTitle: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#2C3E50',
    marginBottom: 10,
    paddingHorizontal: 4,
  },
  // 卡片容器
  cardContainer: {
    backgroundColor: '#FFFFFF',
    borderRadius: 12,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.05,
    shadowRadius: 4,
    elevation: 2,
    overflow: 'hidden',
  },
  membershipBannerImage: {
    width: '100%',
    height: 180,
    borderRadius: 16,
  },
  vipCard: {
    borderRadius: 20,
    padding: 20,
    overflow: 'hidden',
    shadowColor: '#4C3AFF',
    shadowOffset: { width: 0, height: 12 },
    shadowOpacity: 0.2,
    shadowRadius: 20,
    elevation: 6,
  },
  vipCardDecorationLarge: {
    position: 'absolute',
    right: -40,
    top: -30,
    width: 160,
    height: 160,
    borderRadius: 80,
    backgroundColor: 'rgba(255,255,255,0.12)',
  },
  vipCardDecorationSmall: {
    position: 'absolute',
    left: -30,
    bottom: -30,
    width: 140,
    height: 140,
    borderRadius: 70,
    backgroundColor: 'rgba(255,255,255,0.08)',
  },
  vipCardHeader: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'flex-start',
  },
  vipCardHeaderLeft: {
    flex: 1,
    paddingRight: 16,
  },
  vipBadge: {
    flexDirection: 'row',
    alignItems: 'center',
    alignSelf: 'flex-start',
    backgroundColor: 'rgba(255,255,255,0.18)',
    paddingHorizontal: 10,
    paddingVertical: 4,
    borderRadius: 14,
  },
  vipBadgeText: {
    color: '#FFD361',
    fontSize: 12,
    fontWeight: '600',
    marginLeft: 4,
  },
  vipCardTitle: {
    color: '#FFFFFF',
    fontSize: 18,
    fontWeight: '700',
    marginTop: 12,
  },
  vipCardSubtitle: {
    color: 'rgba(255,255,255,0.88)',
    fontSize: 12,
    lineHeight: 18,
    marginTop: 6,
  },
  vipCardIllustration: {
    width: 72,
    height: 72,
    borderRadius: 36,
    backgroundColor: 'rgba(255,255,255,0.18)',
    alignItems: 'center',
    justifyContent: 'center',
  },
  vipCardFooter: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    marginTop: 24,
  },
  vipExpiryInfo: {
    flex: 1,
  },
  vipExpiryLabel: {
    color: 'rgba(255,255,255,0.72)',
    fontSize: 12,
    marginBottom: 6,
  },
  vipExpiryRow: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  vipExpiryValue: {
    color: '#FFFFFF',
    fontSize: 15,
    fontWeight: '600',
    marginLeft: 6,
  },
  vipChangeButton: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: '#FFFFFF',
    paddingHorizontal: 16,
    paddingVertical: 10,
    borderRadius: 22,
  },
  vipChangeButtonText: {
    color: '#2F1767',
    fontSize: 14,
    fontWeight: '600',
    marginLeft: 6,
  },
  // 用户信息区域
  userInfoContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    padding: 16,
  },
  avatarContainer: {
    marginRight: 12,
  },
  avatar: {
    width: 60,
    height: 60,
    borderRadius: 30,
    borderWidth: 2,
    borderColor: '#9370DB',
  },
  userDetails: {
    flex: 1,
  },
  userName: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#2C3E50',
    marginBottom: 4,
    fontFamily: 'AliBold',
  },
  userRole: {
    fontSize: 14,
    color: '#9370DB',
    fontWeight: '500',
    fontFamily: 'AliBold',

  },
  userMemberNumber: {
    fontSize: 10,
    color: '#6C757D',
    marginTop: 4,
    fontFamily: 'AliRegular',
  },
  aiUsageContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    marginTop: 4,
  },
  aiUsageText: {
    fontSize: 10,
    color: '#9370DB',
    marginLeft: 2,
    fontWeight: '500',
    fontFamily: 'AliRegular',
  },
  editButton: {
    backgroundColor: '#9370DB',
    paddingHorizontal: 16,
    paddingVertical: 8,
    borderRadius: 16,
  },
  editButtonGlass: {
    paddingHorizontal: 16,
    paddingVertical: 8,
    borderRadius: 16,
    justifyContent: 'center',
    alignItems: 'center',
  },
  editButtonText: {
    color: 'white',
    fontSize: 14,
    fontWeight: '600',
    fontFamily: 'AliBold',
  },
  editButtonTextGlass: {
    color: 'rgba(147, 112, 219, 1)',
    fontSize: 14,
    fontWeight: '600',
  },
  // 数据统计
  statsContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    padding: 16,
  },
  statItem: {
    alignItems: 'center',
    flex: 1,
  },
  statValue: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#9370DB',
    marginBottom: 4,
    fontFamily: 'AliBold',
  },
  statLabel: {
    fontSize: 12,
    color: '#6C757D',
    fontWeight: '500',
    fontFamily: 'AliRegular',
  },
  badgesRowCard: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingHorizontal: 20,
    paddingVertical: 16,
    borderRadius: 16,
    backgroundColor: '#FFFFFF',
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 6 },
    shadowOpacity: 0.05,
    shadowRadius: 10,
    elevation: 2,
  },
  badgesRowTitle: {
    fontSize: 16,
    fontWeight: '700',
    color: '#111827',
    fontFamily: 'AliBold',
  },
  badgesRowContent: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  badgesStack: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  badgeCompactBubble: {
    width: 32,
    height: 32,
    borderRadius: 22,
    alignItems: 'center',
    justifyContent: 'center',
    marginLeft: 8,
    overflow: 'hidden',
    position: 'relative',
  },
  badgeCompactBubbleEarned: {
    backgroundColor: 'rgba(16, 185, 129, 0.18)',
  },
  badgeCompactBubbleLocked: {
    backgroundColor: 'rgba(226, 232, 240, 0.9)',
  },
  badgeCompactImage: {
    width: '100%',
    height: '100%',
  },
  badgeCompactFallback: {
    ...StyleSheet.absoluteFillObject,
    alignItems: 'center',
    justifyContent: 'center',
  },
  badgeCompactFallbackText: {
    fontSize: 18,
    fontWeight: '600',
    color: '#475467',
    fontFamily: 'AliBold',
  },
  badgeCompactOverlay: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: 'rgba(15, 23, 42, 0.45)',
    alignItems: 'center',
    justifyContent: 'center',
  },
  badgeExtraBubble: {
    backgroundColor: 'rgba(124, 58, 237, 0.12)',
    borderWidth: 1,
    borderColor: 'rgba(124, 58, 237, 0.35)',
  },
  badgeExtraBubbleInline: {
    marginLeft: 12,
  },
  badgeExtraText: {
    fontSize: 14,
    fontWeight: '700',
    color: '#5B21B6',
    fontFamily: 'AliRegular',
  },
  badgesRowEmpty: {
    fontSize: 13,
    color: '#6B7280',
    fontWeight: '500',
    fontFamily: 'AliBold',

  },
  // 菜单项
  menuItem: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingVertical: 14,
    paddingHorizontal: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#F1F3F4',
  },
  menuItemLeft: {
    flexDirection: 'row',
    alignItems: 'center',
    flex: 1,
  },
  menuRight: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  menuRightText: {
    fontSize: 13,
    color: '#6C757D',
    marginRight: 6,
    fontFamily: 'AliRegular',
  },
  iconContainer: {
    width: 32,
    height: 32,
    borderRadius: 6,
    alignItems: 'center',
    justifyContent: 'center',
    marginRight: 12,
  },
  menuItemText: {
    fontSize: 15,
    color: '#2C3E50',
    fontWeight: '500',
  },
  switch: {
    transform: [{ scaleX: 0.8 }, { scaleY: 0.8 }],
  },
  fishRecordContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'flex-start',
    marginBottom: 10,
  },
  fishRecordText: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#2C3E50',
    marginLeft: 4,
    fontFamily: 'AliBold',
  },
  languageModalOverlay: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'stretch',
    padding: 24,
  },
  languageModalBackdrop: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: 'rgba(0,0,0,0.35)',
  },
  languageModalContent: {
    backgroundColor: '#FFFFFF',
    borderRadius: 18,
    padding: 20,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 6 },
    shadowOpacity: 0.15,
    shadowRadius: 12,
    elevation: 6,
  },
  languageModalTitle: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#2C3E50',
    fontFamily: 'AliBold',
  },
  languageModalSubtitle: {
    fontSize: 13,
    color: '#6C757D',
    marginBottom: 4,
    fontFamily: 'AliRegular',
  },
  languageOption: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingVertical: 12,
    paddingHorizontal: 4,
  },
  languageOptionSelected: {
    backgroundColor: 'rgba(147, 112, 219, 0.08)',
    borderRadius: 12,
    paddingHorizontal: 12,
  },
  languageOptionDisabled: {
    opacity: 0.5,
  },
  languageOptionTextGroup: {
    flex: 1,
    paddingRight: 12,
  },
  languageOptionLabel: {
    fontSize: 16,
    fontWeight: '600',
    color: '#2C3E50',
    fontFamily: 'AliBold',
  },
  languageOptionDescription: {
    fontSize: 12,
    color: '#6C757D',
    marginTop: 4,
    fontFamily: 'AliRegular',
  },
  languageModalClose: {
    marginTop: 4,
    alignItems: 'center',
  },
  languageModalCloseText: {
    fontSize: 15,
    fontWeight: '500',
    color: '#9370DB',
    fontFamily: 'AliBold',
  },
});
