import React from 'react';
import { useNavigate } from 'react-router-dom';
import { XStack, YStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text';
import { Button } from '@tamagui/button';
import { Camera, Image as ImageIcon, Trophy, Star, X } from 'lucide-react';
import AppShell from '../components/AppShell';
import PhotoFrameTile from '../components/PhotoFrameTile';
import TaskHeroCard, { type TaskHero, type TaskHeroPhoto } from '../components/TaskHeroCard';
import { useEventData } from '../context/EventDataContext';
import { buildEventPath } from '../lib/routes';
import { useStaggeredReveal } from '../lib/useStaggeredReveal';
import { usePollStats } from '../hooks/usePollStats';
import { fetchGallery } from '../services/photosApi';
import { useTranslation } from '@/guest/i18n/useTranslation';
import { useGuestThemeVariant } from '../lib/guestTheme';
import { useLocale } from '@/guest/i18n/LocaleContext';
import { fetchTasks, type TaskItem } from '../services/tasksApi';
import { useGuestTaskProgress } from '@/guest/hooks/useGuestTaskProgress';
import { fetchEmotions } from '../services/emotionsApi';
import { getBentoSurfaceTokens } from '../lib/bento';
import { useEventBranding } from '@/guest/context/EventBrandingContext';
import { useOptionalGuestIdentity } from '../context/GuestIdentityContext';

type ActionTileProps = {
  label: string;
  icon: React.ReactNode;
  onPress: () => void;
};

type GalleryPreview = {
  id: number;
  imageUrl: string;
};

type TaskPhoto = TaskHeroPhoto & {
  taskId?: number | null;
};

function ActionTile({
  label,
  icon,
  onPress,
  isDark,
}: ActionTileProps & { isDark: boolean }) {
  const surface = getBentoSurfaceTokens(isDark);

  return (
    <Button unstyled onPress={onPress} pressStyle={{ y: 2, opacity: 0.96 }}>
      <YStack
        flex={1}
        minHeight={86}
        padding="$2.5"
        borderRadius="$bento"
        borderWidth={1}
        borderBottomWidth={3}
        borderColor={surface.borderColor}
        borderBottomColor={surface.borderBottomColor}
        backgroundColor={surface.backgroundColor}
        alignItems="center"
        justifyContent="center"
        gap="$1.5"
        style={{
          boxShadow: surface.shadow,
        }}
      >
        {icon}
        <Text
          fontSize={11}
          fontWeight="$7"
          textTransform="none"
          letterSpacing={0.2}
          color="$color"
          opacity={0.8}
          textAlign="center"
        >
          {label}
        </Text>
      </YStack>
    </Button>
  );
}

function QuickStats({
  reveal,
  stats,
  isDark,
}: {
  reveal: number;
  stats: { guestCount: number; likesCount: number };
  isDark: boolean;
}) {
  const { t } = useTranslation();
  const surface = getBentoSurfaceTokens(isDark);
  return (
    <XStack
      gap="$3"
      animation="slow"
      animateOnly={['transform', 'opacity']}
      opacity={reveal >= 3 ? 1 : 0}
      y={reveal >= 3 ? 0 : 12}
    >
      <YStack
        flex={1}
        padding="$3"
        borderRadius="$bento"
        backgroundColor={surface.backgroundColor}
        borderWidth={1}
        borderBottomWidth={3}
        borderColor={surface.borderColor}
        borderBottomColor={surface.borderBottomColor}
        gap="$1"
        style={{
          boxShadow: surface.shadow,
        }}
      >
        <Text fontSize="$4" fontWeight="$8">
          {stats.guestCount}
        </Text>
        <Text fontSize="$1" color="$color" opacity={0.7} textTransform="uppercase" letterSpacing={1.2}>
          {t('homeV2.stats.guestCount', 'Guests')}
        </Text>
      </YStack>
      <YStack
        flex={1}
        padding="$3"
        borderRadius="$bento"
        backgroundColor={surface.backgroundColor}
        borderWidth={1}
        borderBottomWidth={3}
        borderColor={surface.borderColor}
        borderBottomColor={surface.borderBottomColor}
        gap="$1"
        style={{
          boxShadow: surface.shadow,
        }}
      >
        <Text fontSize="$4" fontWeight="$8">
          {stats.likesCount}
        </Text>
        <Text fontSize="$1" color="$color" opacity={0.7} textTransform="uppercase" letterSpacing={1.2}>
          {t('homeV2.stats.likesCount', 'Likes')}
        </Text>
      </YStack>
    </XStack>
  );
}

function normalizeImageUrl(src?: string | null) {
  if (!src) {
    return '';
  }

  if (/^https?:/i.test(src)) {
    return src;
  }

  let cleanPath = src.replace(/^\/+/g, '').replace(/\/+/g, '/');
  if (!cleanPath.startsWith('storage/')) {
    cleanPath = `storage/${cleanPath}`;
  }

  return `/${cleanPath}`.replace(/\/+/g, '/');
}

export default function HomeScreen() {
  const { tasksEnabled, token, event } = useEventData();
  const navigate = useNavigate();
  const revealStage = useStaggeredReveal({ steps: 5, intervalMs: 140, delayMs: 120 });
  const { stats } = usePollStats(token ?? null);
  const { t } = useTranslation();
  const { locale } = useLocale();
  const { isCompleted } = useGuestTaskProgress(token ?? undefined);
  const { branding } = useEventBranding();
  const identity = useOptionalGuestIdentity();
  const [galleryPhotos, setGalleryPhotos] = React.useState<TaskPhoto[]>([]);
  const [galleryLoading, setGalleryLoading] = React.useState(false);
  const [galleryError, setGalleryError] = React.useState<string | null>(null);
  const [tasks, setTasks] = React.useState<TaskHero[]>([]);
  const [currentTask, setCurrentTask] = React.useState<TaskHero | null>(null);
  const [taskLoading, setTaskLoading] = React.useState(false);
  const [taskError, setTaskError] = React.useState<string | null>(null);
  const [hasSwiped, setHasSwiped] = React.useState(false);
  const { isDark } = useGuestThemeVariant();
  const bentoSurface = getBentoSurfaceTokens(isDark);
  const mutedButton = isDark ? 'rgba(255, 255, 255, 0.08)' : 'rgba(255, 255, 255, 0.75)';
  const mutedButtonBorder = isDark ? 'rgba(255, 255, 255, 0.2)' : 'rgba(15, 23, 42, 0.08)';
  const cardShadow = bentoSurface.shadow;
  const welcomeStorageKey = token ? `guestWelcomeDismissed_${token}` : 'guestWelcomeDismissed';
  const [welcomeVisible, setWelcomeVisible] = React.useState(true);
  const eventName = event?.name ?? t('galleryPage.hero.eventFallback', 'Event');
  const guestName = identity?.name?.trim() ? identity.name.trim() : t('home.fallbackGuestName', 'Gast');
  const welcomeTemplate = branding?.welcomeMessage?.trim()
    ? branding.welcomeMessage.trim()
    : t('homeV2.welcome.message', 'Welcome to {eventName}.');
  const welcomeMessage = welcomeTemplate
    .replace('{eventName}', eventName)
    .replace('{name}', guestName);
  const dismissWelcome = React.useCallback(() => {
    setWelcomeVisible(false);
    if (typeof window === 'undefined') return;
    try {
      window.sessionStorage.setItem(welcomeStorageKey, '1');
    } catch {
      // ignore storage errors
    }
  }, [welcomeStorageKey]);

  const goTo = (path: string) => () => navigate(buildEventPath(token, path));

  const recentTaskIdsRef = React.useRef<number[]>([]);

  React.useEffect(() => {
    if (typeof window === 'undefined') return;
    try {
      const stored = window.sessionStorage.getItem(welcomeStorageKey);
      setWelcomeVisible(stored !== '1');
    } catch {
      setWelcomeVisible(true);
    }
  }, [welcomeStorageKey]);

  const rings = [
    {
      label: t('home.actions.items.upload.label', 'Upload photo'),
      icon: <Camera size={18} color={isDark ? '#F8FAFF' : '#0F172A'} />,
      path: '/upload',
    },
    {
      label: t('homeV2.rings.newUploads', 'New uploads'),
      icon: <ImageIcon size={18} color={isDark ? '#F8FAFF' : '#0F172A'} />,
      path: '/gallery',
    },
    {
      label: t('homeV2.rings.topMoments', 'Top moments'),
      icon: <Star size={18} color={isDark ? '#F8FAFF' : '#0F172A'} />,
      path: '/gallery',
    },
    {
      label: t('navigation.achievements', 'Achievements'),
      icon: <Trophy size={18} color={isDark ? '#F8FAFF' : '#0F172A'} />,
      path: '/achievements',
    },
  ];

  const mapTaskItem = React.useCallback((task: TaskItem, emotionMap: Record<string, string>): TaskHero | null => {
    const record = task as Record<string, unknown>;
    const id = Number(record.id ?? record.task_id ?? 0);
    const title =
      typeof record.title === 'string'
        ? record.title
        : typeof record.name === 'string'
          ? record.name
          : '';
    if (!id || !title) return null;

    const description =
      typeof record.description === 'string'
        ? record.description
        : typeof record.prompt === 'string'
          ? record.prompt
          : null;
    const instructions =
      typeof record.instructions === 'string'
        ? record.instructions
        : typeof record.instruction === 'string'
          ? record.instruction
          : null;
    const durationValue = record.duration ?? record.time_limit ?? record.minutes ?? null;
    const duration = typeof durationValue === 'number' ? durationValue : Number(durationValue);
    const emotionValue = record.emotion;
    const slugValue = typeof record.emotion_slug === 'string' ? (record.emotion_slug as string) : undefined;
    const nameValue = typeof record.emotion_name === 'string'
      ? (record.emotion_name as string)
      : typeof record.emotion_title === 'string'
        ? (record.emotion_title as string)
        : slugValue
          ? emotionMap[slugValue]
          : undefined;
    const emotion =
      typeof emotionValue === 'object' && emotionValue
        ? {
            slug: typeof (emotionValue as Record<string, unknown>).slug === 'string'
              ? (emotionValue as Record<string, unknown>).slug as string
              : undefined,
            name: typeof (emotionValue as Record<string, unknown>).name === 'string'
              ? (emotionValue as Record<string, unknown>).name as string
              : undefined,
            emoji: typeof (emotionValue as Record<string, unknown>).emoji === 'string'
              ? (emotionValue as Record<string, unknown>).emoji as string
              : undefined,
          }
        : {
            slug: slugValue,
            name: nameValue,
          };

    return {
      id,
      title,
      description,
      instructions,
      duration: Number.isFinite(duration) ? duration : null,
      emotion,
    };
  }, []);

  const selectRandomTask = React.useCallback(
    (list: TaskHero[]) => {
      if (!list.length) {
        setCurrentTask(null);
        return;
      }
      const avoidIds = recentTaskIdsRef.current;
      const available = list.filter((task) => !isCompleted(task.id));
      const base = available.length ? available : list;
      let candidates = base.filter((task) => !avoidIds.includes(task.id));
      if (!candidates.length) {
        candidates = base;
      }
      const chosen = candidates[Math.floor(Math.random() * candidates.length)];
      setCurrentTask(chosen);
      recentTaskIdsRef.current = [...avoidIds.filter((id) => id !== chosen.id), chosen.id].slice(-3);
    },
    [isCompleted]
  );

  React.useEffect(() => {
    if (!token) {
      setGalleryPhotos([]);
      setGalleryError(null);
      return;
    }

    let active = true;
    setGalleryLoading(true);
    setGalleryError(null);

    fetchGallery(token, { limit: 72, locale })
      .then((response) => {
        if (!active) return;
        const photos = Array.isArray(response.data) ? response.data : [];
        const mapped = photos.map((photo) => {
          const record = photo as Record<string, unknown>;
          const id = Number(record.id ?? 0);
          const imageUrl = normalizeImageUrl(
            (record.thumbnail_url as string | null | undefined)
              ?? (record.thumbnail_path as string | null | undefined)
              ?? (record.file_path as string | null | undefined)
              ?? (record.full_url as string | null | undefined)
              ?? (record.url as string | null | undefined)
              ?? (record.image_url as string | null | undefined)
          );
          const taskId = Number(record.task_id ?? record.taskId ?? 0);
          const likesCount =
            typeof record.likes_count === 'number'
              ? record.likes_count
              : typeof record.likesCount === 'number'
                ? record.likesCount
                : undefined;
          return {
            id,
            imageUrl,
            taskId: Number.isFinite(taskId) && taskId > 0 ? taskId : null,
            likesCount,
          };
        });
        setGalleryPhotos(mapped.filter((item) => item.id && item.imageUrl));
      })
      .catch((error) => {
        console.error('Failed to load gallery preview', error);
        if (active) {
          setGalleryPhotos([]);
          setGalleryError(t('gallery.error', 'Gallery could not be loaded.'));
        }
      })
      .finally(() => {
        if (active) {
          setGalleryLoading(false);
        }
      });

    return () => {
      active = false;
    };
  }, [locale, t, token]);

  const reloadTasks = React.useCallback(() => {
    if (!token || !tasksEnabled) {
      setTasks([]);
      setCurrentTask(null);
      setTaskError(null);
      setTaskLoading(false);
      return Promise.resolve();
    }

    setTaskLoading(true);
    setTaskError(null);

    return Promise.all([
      fetchTasks(token, { locale }),
      fetchEmotions(token, locale),
    ])
      .then(([taskList, emotionList]) => {
        const nextMap: Record<string, string> = {};
        for (const emotion of emotionList) {
          const record = emotion as Record<string, unknown>;
          const slug = typeof record.slug === 'string' ? record.slug : '';
          const title = typeof record.title === 'string' ? record.title : typeof record.name === 'string' ? record.name : '';
          if (slug) {
            nextMap[slug] = title || slug;
          }
        }
        const mapped = taskList.map((task) => mapTaskItem(task, nextMap)).filter(Boolean) as TaskHero[];
        setTasks(mapped);
      })
      .catch((error) => {
        console.error('Failed to load tasks', error);
        setTasks([]);
        setCurrentTask(null);
        setTaskError(t('tasks.error', 'Tasks could not be loaded.'));
      })
      .finally(() => {
        setTaskLoading(false);
      });
  }, [locale, mapTaskItem, t, tasksEnabled, token]);

  React.useEffect(() => {
    let active = true;
    if (!token || !tasksEnabled) {
      setTasks([]);
      setCurrentTask(null);
      setTaskError(null);
      setTaskLoading(false);
      return;
    }

    setTaskLoading(true);
    setTaskError(null);

    Promise.all([
      fetchTasks(token, { locale }),
      fetchEmotions(token, locale),
    ])
      .then(([taskList, emotionList]) => {
        if (!active) return;
        const nextMap: Record<string, string> = {};
        for (const emotion of emotionList) {
          const record = emotion as Record<string, unknown>;
          const slug = typeof record.slug === 'string' ? record.slug : '';
          const title = typeof record.title === 'string' ? record.title : typeof record.name === 'string' ? record.name : '';
          if (slug) {
            nextMap[slug] = title || slug;
          }
        }
        const mapped = taskList.map((task) => mapTaskItem(task, nextMap)).filter(Boolean) as TaskHero[];
        setTasks(mapped);
      })
      .catch((error) => {
        console.error('Failed to load tasks', error);
        if (active) {
          setTasks([]);
          setCurrentTask(null);
          setTaskError(t('tasks.error', 'Tasks could not be loaded.'));
        }
      })
      .finally(() => {
        if (active) {
          setTaskLoading(false);
        }
      });

    return () => {
      active = false;
    };
  }, [locale, mapTaskItem, t, tasksEnabled, token]);

  React.useEffect(() => {
    if (!tasksEnabled || tasks.length === 0) {
      setCurrentTask(null);
      return;
    }
    if (currentTask && tasks.some((task) => task.id === currentTask.id) && !isCompleted(currentTask.id)) {
      return;
    }
    selectRandomTask(tasks);
  }, [currentTask, isCompleted, selectRandomTask, tasks, tasksEnabled]);

  const preview = React.useMemo<GalleryPreview[]>(
    () =>
      galleryPhotos.slice(0, 4).map((photo) => ({
        id: photo.id,
        imageUrl: photo.imageUrl,
      })),
    [galleryPhotos]
  );
  const taskPhotos = React.useMemo<TaskHeroPhoto[]>(() => {
    if (!currentTask) return [];
    const matches = galleryPhotos.filter((photo) => photo.taskId === currentTask.id);
    if (matches.length >= 6) {
      return matches.slice(0, 6).map((photo) => ({
        id: photo.id,
        imageUrl: photo.imageUrl,
        likesCount: photo.likesCount,
      }));
    }
    const fallback = galleryPhotos.filter((photo) => photo.taskId !== currentTask.id);
    const combined = [...matches, ...fallback].slice(0, 6);
    return combined.map((photo) => ({
      id: photo.id,
      imageUrl: photo.imageUrl,
      likesCount: photo.likesCount,
    }));
  }, [currentTask, galleryPhotos]);
  const openPreviewPhoto = React.useCallback(
    (photoId: number) => {
      navigate(buildEventPath(token, `/gallery?photo=${photoId}`));
    },
    [navigate, token]
  );
  const openTaskPhoto = React.useCallback(
    (photoId: number) => {
      if (!currentTask) return;
      navigate(buildEventPath(token, `/gallery?photo=${photoId}&task=${currentTask.id}`));
    },
    [currentTask, navigate, token]
  );
  const handleStartTask = React.useCallback(() => {
    if (!currentTask) return;
    navigate(buildEventPath(token, `/upload?taskId=${currentTask.id}`));
  }, [currentTask, navigate, token]);
  const handleViewSimilar = React.useCallback(() => {
    if (!currentTask) return;
    navigate(buildEventPath(token, `/gallery?task=${currentTask.id}`));
  }, [currentTask, navigate, token]);
  const handleShuffle = React.useCallback(() => {
    selectRandomTask(tasks);
    setHasSwiped(true);
  }, [selectRandomTask, tasks]);

  return (
    <AppShell>
        <YStack gap="$4">
        {welcomeVisible && welcomeMessage.trim() ? (
          <YStack
            gap="$3"
            animation="slow"
            animateOnly={['transform', 'opacity']}
            opacity={revealStage >= 1 ? 1 : 0}
            y={revealStage >= 1 ? 0 : 12}
          >
            <YStack
              position="relative"
              padding="$4"
              borderRadius="$bentoLg"
              backgroundColor={bentoSurface.backgroundColor}
              borderWidth={1}
              borderBottomWidth={3}
              borderColor={bentoSurface.borderColor}
              borderBottomColor={bentoSurface.borderBottomColor}
              gap="$2"
              style={{
                boxShadow: cardShadow,
              }}
            >
              <Button
                unstyled
                position="absolute"
                top={-12}
                right={-12}
                width={34}
                height={34}
                borderRadius={999}
                backgroundColor={bentoSurface.backgroundColor}
                borderWidth={1}
                borderColor={bentoSurface.borderColor}
                alignItems="center"
                justifyContent="center"
                onPress={dismissWelcome}
                pressStyle={{ y: 2 }}
                style={{
                  boxShadow: isDark ? '0 6px 0 rgba(0, 0, 0, 0.45)' : '0 6px 0 rgba(15, 23, 42, 0.2)',
                }}
                aria-label={t('common.actions.close', 'Close')}
              >
                <X size={14} color={isDark ? '#F8FAFF' : '#0F172A'} />
              </Button>
              <Text fontSize="$2" color="$color" opacity={0.75} textTransform="uppercase" letterSpacing={1.4}>
                {t('homeV2.welcome.label', 'Welcome')}
              </Text>
              <Text fontSize="$6" fontFamily="$display" fontWeight="$8">
                {welcomeMessage}
              </Text>
            </YStack>
          </YStack>
        ) : null}

        {tasksEnabled ? (
          <YStack
            animation="slow"
            animateOnly={['transform', 'opacity']}
            opacity={revealStage >= 2 ? 1 : 0}
            y={revealStage >= 2 ? 0 : 16}
          >
            <TaskHeroCard
              task={currentTask}
              loading={taskLoading}
              error={taskError}
              hasSwiped={hasSwiped}
              onSwiped={() => setHasSwiped(true)}
              onStart={handleStartTask}
              onShuffle={handleShuffle}
              onViewSimilar={handleViewSimilar}
              onRetry={reloadTasks}
              onOpenPhoto={openTaskPhoto}
              isCompleted={isCompleted(currentTask?.id)}
              photos={taskPhotos}
              photosLoading={galleryLoading}
              photosError={galleryError}
            />
          </YStack>
        ) : (
          <YStack
            padding="$4"
            borderRadius="$bento"
            backgroundColor={bentoSurface.backgroundColor}
            borderWidth={1}
            borderBottomWidth={3}
            borderColor={bentoSurface.borderColor}
            borderBottomColor={bentoSurface.borderBottomColor}
            gap="$3"
            animation="slow"
            animateOnly={['transform', 'opacity']}
            opacity={revealStage >= 2 ? 1 : 0}
            y={revealStage >= 2 ? 0 : 16}
            style={{
              backgroundImage: isDark
                ? 'linear-gradient(135deg, rgba(79, 209, 255, 0.18), rgba(255, 79, 216, 0.12))'
                : 'linear-gradient(135deg, color-mix(in oklab, var(--guest-secondary, #F43F5E) 10%, white), color-mix(in oklab, var(--guest-primary, #FF5A5F) 10%, white))',
              boxShadow: cardShadow,
            }}
          >
            <XStack alignItems="center" gap="$2">
              <Camera size={18} color={isDark ? '#F8FAFF' : '#0F172A'} />
              <Text fontSize="$3" fontWeight="$7">
                {t('homeV2.captureReady.label', 'Capture ready')}
              </Text>
            </XStack>
            <Text fontSize="$7" fontFamily="$display" fontWeight="$8">
              {t('homeV2.captureReady.title', 'Add a photo to the shared gallery')}
            </Text>
            <Text fontSize="$3" color="$color" opacity={0.75}>
              {t('homeV2.captureReady.subtitle', 'Quick add from your camera or device.')}
            </Text>
            <Button size="$4" backgroundColor="$primary" borderRadius="$pill" onPress={goTo('/upload')}>
              {t('homeV2.captureReady.cta', 'Upload / Take photo')}
            </Button>
          </YStack>
        )}

        <QuickStats
          reveal={revealStage}
          stats={{ guestCount: stats.guestCount, likesCount: stats.likesCount }}
          isDark={isDark}
        />

        <YStack
          padding="$4"
          borderRadius="$bentoLg"
          backgroundColor={bentoSurface.backgroundColor}
          borderWidth={1}
          borderBottomWidth={3}
          borderColor={bentoSurface.borderColor}
          borderBottomColor={bentoSurface.borderBottomColor}
          gap="$3"
          animation="slow"
          animateOnly={['transform', 'opacity']}
          opacity={revealStage >= 4 ? 1 : 0}
          y={revealStage >= 4 ? 0 : 16}
          style={{
            boxShadow: cardShadow,
          }}
        >
          <XStack alignItems="center" justifyContent="space-between">
            <Text fontSize="$5" fontWeight="$8" fontFamily="$display">
              {t('homeV2.galleryPreview.title', 'Gallery preview')}
            </Text>
            <Button
              size="$3"
              backgroundColor={mutedButton}
              borderRadius="$pill"
              borderWidth={1}
              borderColor={mutedButtonBorder}
              onPress={goTo('/gallery')}
            >
              {t('homeV2.galleryPreview.cta', 'View all')}
            </Button>
          </XStack>
          <XStack
            gap="$2"
            style={{
              overflowX: 'auto',
              WebkitOverflowScrolling: 'touch',
              paddingBottom: 6,
            }}
          >
            {(galleryLoading || preview.length === 0 ? [1, 2, 3, 4] : preview).map((tile) => {
              if (typeof tile === 'number') {
                return (
                  <YStack key={tile} flexShrink={0} width={140}>
                    <PhotoFrameTile height={110} borderRadius="$bento" shimmer shimmerDelayMs={tile * 140} />
                  </YStack>
                );
              }
              return (
                <YStack key={tile.id} flexShrink={0} width={140}>
                  <Button
                    unstyled
                    onPress={() => openPreviewPhoto(tile.id)}
                    aria-label={t('galleryPage.photo.alt', { id: tile.id, suffix: '' }, `Foto ${tile.id}`)}
                  >
                    <PhotoFrameTile height={110} borderRadius="$bento">
                      <YStack
                        flex={1}
                        width="100%"
                        height="100%"
                        style={{
                          backgroundImage: `url(${tile.imageUrl})`,
                          backgroundSize: 'cover',
                          backgroundPosition: 'center',
                        }}
                      />
                    </PhotoFrameTile>
                  </Button>
                </YStack>
              );
            })}
          </XStack>
        </YStack>

        <YStack
          gap="$3"
          animation="slow"
          animateOnly={['transform', 'opacity']}
          opacity={revealStage >= 5 ? 1 : 0}
          y={revealStage >= 5 ? 0 : 12}
        >
          <XStack gap="$2" flexWrap="nowrap">
            {rings.map((ring) => (
              <YStack key={ring.label} flex={1} minWidth={0}>
                <ActionTile label={ring.label} icon={ring.icon} onPress={goTo(ring.path)} isDark={isDark} />
              </YStack>
            ))}
          </XStack>
        </YStack>
        <YStack height={70} />
      </YStack>
    </AppShell>
  );
}
