import React from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { useQuery } from '@tanstack/react-query';
import { Bell, CheckCircle2, Download, Image as ImageIcon, ListTodo, MessageCircle, QrCode, Settings, ShieldCheck, Smartphone, Users, Sparkles } from 'lucide-react';
import { YStack, XStack } from '@tamagui/stacks';
import { SizableText as Text } from '@tamagui/text';
import { Pressable } from '@tamagui/react-native-web-lite';
import { MobileShell, renderEventLocation } from './components/MobileShell';
import { MobileCard, CTAButton, KpiTile, ActionTile, PillBadge, SkeletonCard } from './components/Primitives';
import { MobileSheet } from './components/Sheet';
import { adminPath, ADMIN_WELCOME_BASE_PATH } from '../constants';
import { useEventContext } from '../context/EventContext';
import { fetchOnboardingStatus, getEventStats, EventStats, TenantEvent, getEvents, getTenantPackagesOverview } from '../api';
import { formatEventDate, isBrandingAllowed, resolveEngagementMode, resolveEventDisplayName } from '../lib/events';
import { useAdminPushSubscription } from './hooks/useAdminPushSubscription';
import { useDevicePermissions } from './hooks/useDevicePermissions';
import { useInstallPrompt } from './hooks/useInstallPrompt';
import { getTourSeen, resolveTourStepKeys, setTourSeen, type TourStepKey } from './lib/mobileTour';
import { collectPackageFeatures, formatPackageLimit, getPackageFeatureLabel, getPackageLimitEntries } from './lib/packageSummary';
import { trackOnboarding } from '../api';
import { useAuth } from '../auth/context';
import { ADMIN_ACTION_COLORS, ADMIN_MOTION, useAdminTheme } from './theme';

type DeviceSetupProps = {
  installPrompt: ReturnType<typeof useInstallPrompt>;
  pushState: ReturnType<typeof useAdminPushSubscription>;
  devicePermissions: ReturnType<typeof useDevicePermissions>;
  onOpenSettings: () => void;
};

export default function MobileDashboardPage() {
  const navigate = useNavigate();
  const location = useLocation();
  const { t, i18n } = useTranslation('management');
  const { events, activeEvent, hasEvents, hasMultipleEvents, isLoading, selectEvent } = useEventContext();
  const { status } = useAuth();
  const [fallbackEvents, setFallbackEvents] = React.useState<TenantEvent[]>([]);
  const [fallbackLoading, setFallbackLoading] = React.useState(false);
  const [fallbackAttempted, setFallbackAttempted] = React.useState(false);
  const [tourOpen, setTourOpen] = React.useState(false);
  const [tourStep, setTourStep] = React.useState(0);
  const [summaryOpen, setSummaryOpen] = React.useState(false);
  const [summarySeenOverride, setSummarySeenOverride] = React.useState<number | null>(null);
  const onboardingTrackedRef = React.useRef(false);
  const installPrompt = useInstallPrompt();
  const pushState = useAdminPushSubscription();
  const devicePermissions = useDevicePermissions();
  const { textStrong, muted, border, surface, accentSoft, primary } = useAdminTheme();
  const text = textStrong;
  const accentText = primary;

  const { data: stats, isLoading: statsLoading } = useQuery<EventStats | null>({
    queryKey: ['mobile', 'dashboard', 'stats', activeEvent?.slug],
    enabled: Boolean(activeEvent?.slug),
    queryFn: async () => {
      if (!activeEvent?.slug) return null;
      return await getEventStats(activeEvent.slug);
    },
  });
  const tasksEnabled =
    resolveEngagementMode(activeEvent ?? undefined) !== 'photo_only';

  const locale = i18n.language?.startsWith('en') ? 'en-GB' : 'de-DE';
  const { data: dashboardEvents } = useQuery<TenantEvent[]>({
    queryKey: ['mobile', 'dashboard', 'events'],
    queryFn: () => getEvents({ force: true }),
    staleTime: 60_000,
  });
  const { data: onboardingStatus, isLoading: onboardingLoading } = useQuery({
    queryKey: ['mobile', 'onboarding', 'status'],
    queryFn: fetchOnboardingStatus,
    staleTime: 60_000,
  });
  const { data: packagesOverview, isLoading: packagesLoading, isError: packagesError } = useQuery({
    queryKey: ['mobile', 'onboarding', 'packages-overview'],
    queryFn: () => getTenantPackagesOverview({ force: true }),
    staleTime: 60_000,
  });
  const effectiveEvents = events.length ? events : dashboardEvents?.length ? dashboardEvents : fallbackEvents;
  const effectiveHasEvents = hasEvents || Boolean(dashboardEvents?.length) || fallbackEvents.length > 0;
  const effectiveMultiple =
    hasMultipleEvents || (dashboardEvents?.length ?? 0) > 1 || fallbackEvents.length > 1;
  const tourTargetSlug = activeEvent?.slug ?? effectiveEvents[0]?.slug ?? null;
  const tourStepKeys = React.useMemo(() => resolveTourStepKeys(effectiveHasEvents), [effectiveHasEvents]);

  React.useEffect(() => {
    if (status !== 'authenticated' || onboardingTrackedRef.current) {
      return;
    }

    onboardingTrackedRef.current = true;

    if (typeof window !== 'undefined') {
      try {
        const stored = window.localStorage.getItem('admin-onboarding-opened-v1');
        if (stored) {
          return;
        }

        window.localStorage.setItem('admin-onboarding-opened-v1', '1');
      } catch {
        // Ignore storage errors.
      }
    }

    void trackOnboarding('admin_app_opened');
  }, [status]);

  const forceTour = React.useMemo(() => {
    const params = new URLSearchParams(location.search);
    return params.get('tour') === '1';
  }, [location.search]);

  React.useEffect(() => {
    if (forceTour) {
      setTourStep(0);
      setTourOpen(true);
      setTourSeen(false);
      navigate(location.pathname, { replace: true });
      return;
    }

    if (getTourSeen()) {
      return;
    }

    setTourOpen(true);
  }, [forceTour, location.pathname, navigate]);

  const activePackage =
    packagesOverview?.activePackage ?? packagesOverview?.packages?.find((pkg) => pkg.active) ?? null;
  const remainingEvents = activePackage?.remaining_events ?? null;
  const summarySeenPackageId =
    summarySeenOverride ?? onboardingStatus?.steps?.summary_seen_package_id ?? null;
  const hasSummaryPackage =
    Boolean(activePackage?.id && activePackage.id !== summarySeenPackageId);
  const shouldRedirectToBilling =
    !packagesLoading &&
    !packagesError &&
    !effectiveHasEvents &&
    (activePackage === null || (remainingEvents !== null && remainingEvents <= 0));

  React.useEffect(() => {
    if (packagesLoading || !shouldRedirectToBilling) {
      return;
    }

    navigate(adminPath('/mobile/billing#packages'), { replace: true });
  }, [navigate, packagesLoading, shouldRedirectToBilling]);

  React.useEffect(() => {
    if (packagesLoading || packagesError || onboardingLoading) {
      return;
    }

    if (shouldRedirectToBilling) {
      return;
    }

    if (hasSummaryPackage) {
      setSummaryOpen(true);
    }
  }, [hasSummaryPackage, onboardingLoading, packagesLoading, shouldRedirectToBilling]);

  const markTourSeen = React.useCallback(() => {
    if (typeof window === 'undefined') {
      return;
    }

    setTourSeen(true);
  }, []);

  const closeTour = React.useCallback(() => {
    setTourOpen(false);
    markTourSeen();
  }, [markTourSeen]);

  const tourSteps = React.useMemo(() => {
    const stepMap: Record<TourStepKey, {
      key: TourStepKey;
      icon: React.ComponentType<{ size?: number; color?: string }>;
      title: string;
      body: string;
      actionLabel?: string;
      action?: () => void;
      showAction?: boolean;
    }> = {
      event: {
        key: 'event',
        icon: Sparkles,
        title: t('mobileTour.eventTitle', 'Create your first event'),
        body: t('mobileTour.eventBody', 'Add the date, location, and package to unlock sharing.'),
        actionLabel: t('mobileTour.eventAction', 'Create event'),
        action: () => {
          closeTour();
          navigate(adminPath('/mobile/events/new'));
        },
        showAction: true,
      },
      qr: {
        key: 'qr',
        icon: QrCode,
        title: t('mobileTour.qrTitle', 'Share your QR code'),
        body: t('mobileTour.qrBody', 'Guests join instantly by scanning or using the invite link.'),
        actionLabel: t('mobileTour.qrAction', 'Open QR'),
        action: () => {
          if (!tourTargetSlug) {
            return;
          }
          closeTour();
          navigate(adminPath(`/mobile/events/${tourTargetSlug}/qr`));
        },
        showAction: Boolean(tourTargetSlug),
      },
      photos: {
        key: 'photos',
        icon: ImageIcon,
        title: t('mobileTour.photosTitle', 'Moderate uploads'),
        body: t('mobileTour.photosBody', 'Approve, feature, or hide photos with quick swipes.'),
        actionLabel: t('mobileTour.photosAction', 'Review photos'),
        action: () => {
          if (!tourTargetSlug) {
            return;
          }
          closeTour();
          navigate(adminPath(`/mobile/events/${tourTargetSlug}/photos`));
        },
        showAction: Boolean(tourTargetSlug),
      },
      push: {
        key: 'push',
        icon: Bell,
        title: t('mobileTour.pushTitle', 'Stay in the loop'),
        body: t('mobileTour.pushBody', 'Enable push alerts to catch limits and new uploads fast.'),
        actionLabel: t('mobileTour.pushAction', 'Notification settings'),
        action: () => {
          closeTour();
          navigate(adminPath('/mobile/settings'));
        },
        showAction: true,
      },
    };

    return tourStepKeys.map((key) => stepMap[key]);
  }, [closeTour, navigate, t, tourStepKeys, tourTargetSlug]);

  const activeTourStep = tourSteps[tourStep] ?? tourSteps[0];
  const totalTourSteps = tourSteps.length;

  React.useEffect(() => {
    if (tourStep >= tourSteps.length) {
      setTourStep(0);
    }
  }, [tourStep, tourSteps.length]);

  const handleTourNext = React.useCallback(() => {
    if (tourStep >= totalTourSteps - 1) {
      closeTour();
      return;
    }
    setTourStep((prev) => prev + 1);
  }, [closeTour, tourStep, totalTourSteps]);

  const handleTourBack = React.useCallback(() => {
    setTourStep((prev) => Math.max(prev - 1, 0));
  }, []);

  const tourSheet = activeTourStep ? (
    <MobileSheet open={tourOpen} title={t('mobileTour.title', 'Quick tour')} onClose={closeTour}>
      <YStack space="$2.5">
        <XStack alignItems="center" justifyContent="space-between">
          <Text fontSize="$xs" color={muted}>
            {t('mobileTour.progress', 'Step {{current}} of {{total}}', {
              current: tourStep + 1,
              total: totalTourSteps,
            })}
          </Text>
          <Pressable onPress={closeTour}>
            <Text fontSize="$xs" color={muted} textDecorationLine="underline">
              {t('mobileTour.skip', 'Skip')}
            </Text>
          </Pressable>
        </XStack>
        <YStack space="$2">
          <XStack alignItems="center" space="$2">
            <XStack
              width={40}
              height={40}
              borderRadius={14}
              alignItems="center"
              justifyContent="center"
              backgroundColor={accentSoft}
            >
              <activeTourStep.icon size={18} color={accentText} />
            </XStack>
            <Text fontSize="$lg" fontWeight="800" color={text}>
              {activeTourStep.title}
            </Text>
          </XStack>
          <Text fontSize="$sm" color={muted}>
            {activeTourStep.body}
          </Text>
          {activeTourStep.showAction && activeTourStep.action && activeTourStep.actionLabel ? (
            <CTAButton
              label={activeTourStep.actionLabel}
              tone="ghost"
              fullWidth={false}
              onPress={activeTourStep.action}
            />
          ) : null}
        </YStack>
        <XStack space="$2" justifyContent="space-between">
          {tourStep > 0 ? (
            <CTAButton label={t('mobileTour.back', 'Back')} tone="ghost" fullWidth={false} onPress={handleTourBack} />
          ) : (
            <XStack />
          )}
          <CTAButton
            label={tourStep >= totalTourSteps - 1 ? t('mobileTour.done', 'Done') : t('mobileTour.next', 'Next')}
            fullWidth={false}
            onPress={handleTourNext}
          />
        </XStack>
      </YStack>
    </MobileSheet>
  ) : null;

  const handleSummaryClose = React.useCallback(() => {
    setSummaryOpen(false);
    if (activePackage?.id) {
      setSummarySeenOverride(activePackage.id);
      void trackOnboarding('summary_seen', { package_id: activePackage.id });
    }
  }, [activePackage?.id]);

  const packageSummarySheet = activePackage ? (
    <PackageSummarySheet
      open={summaryOpen}
      onClose={handleSummaryClose}
      onContinue={() => {
        handleSummaryClose();
        navigate(adminPath('/mobile/events/new'));
      }}
      packageName={activePackage.package_name ?? t('mobileDashboard.packageSummary.fallbackTitle', 'Package summary')}
      remainingEvents={remainingEvents}
      purchasedAt={activePackage.purchased_at}
      expiresAt={activePackage.expires_at}
      limits={activePackage.package_limits ?? null}
      features={activePackage.features ?? null}
      locale={locale}
    />
  ) : null;
  const showPackageSummaryBanner =
    Boolean(activePackage && summarySeenPackageId === activePackage.id) &&
    !summaryOpen &&
    !packagesLoading &&
    !packagesError;

  React.useEffect(() => {
    if (events.length || isLoading || fallbackLoading || fallbackAttempted) {
      return;
    }
    setFallbackAttempted(true);
    setFallbackLoading(true);
    getEvents({ force: true })
      .then((list: TenantEvent[]) => {
        setFallbackEvents(list ?? []);
        if (list?.length === 1 && !activeEvent) {
          selectEvent(list[0]?.slug ?? null);
        }
      })
      .catch(() => {
        setFallbackEvents([]);
      })
      .finally(() => setFallbackLoading(false));
  }, [events.length, isLoading, activeEvent, selectEvent, fallbackLoading, fallbackAttempted]);

  if (isLoading || fallbackLoading) {
    return (
      <MobileShell activeTab="home" title={t('mobileDashboard.title', 'Dashboard')}>
          <YStack space="$2">
            {Array.from({ length: 3 }).map((_, idx) => (
            <SkeletonCard key={`sk-${idx}`} height={110} />
            ))}
          </YStack>
          {tourSheet}
          {packageSummarySheet}
        </MobileShell>
      );
  }

  if (!effectiveHasEvents) {
    return (
      <MobileShell activeTab="home" title={t('mobileDashboard.title', 'Dashboard')}>
        {showPackageSummaryBanner ? (
          <PackageSummaryBanner
            packageName={activePackage?.package_name}
            onOpen={() => setSummaryOpen(true)}
          />
        ) : null}
        <OnboardingEmptyState
          installPrompt={installPrompt}
          pushState={pushState}
          devicePermissions={devicePermissions}
          onOpenSettings={() => navigate(adminPath('/mobile/settings'))}
        />
        {tourSheet}
        {packageSummarySheet}
      </MobileShell>
    );
  }

  if (effectiveMultiple && !activeEvent) {
    return (
      <MobileShell
        activeTab="home"
        title={t('mobileDashboard.title', 'Dashboard')}
        subtitle={t('mobileDashboard.selectEvent', 'Select an event to continue')}
      >
        {showPackageSummaryBanner ? (
          <PackageSummaryBanner
            packageName={activePackage?.package_name}
            onOpen={() => setSummaryOpen(true)}
          />
        ) : null}
        <EventPickerList events={effectiveEvents} locale={locale} text={text} muted={muted} border={border} />
        {tourSheet}
        {packageSummarySheet}
      </MobileShell>
    );
  }

  return (
    <MobileShell
      activeTab="home"
      title={resolveEventDisplayName(activeEvent ?? undefined)}
      subtitle={formatEventDate(activeEvent?.event_date, locale) ?? undefined}
    >
      {showPackageSummaryBanner ? (
        <PackageSummaryBanner
          packageName={activePackage?.package_name}
          onOpen={() => setSummaryOpen(true)}
        />
      ) : null}
      <DeviceSetupCard
        installPrompt={installPrompt}
        pushState={pushState}
        devicePermissions={devicePermissions}
        onOpenSettings={() => navigate(adminPath('/mobile/settings'))}
      />
      <FeaturedActions
        tasksEnabled={tasksEnabled}
        onReviewPhotos={() => activeEvent?.slug && navigate(adminPath(`/mobile/events/${activeEvent.slug}/photos`))}
        onManageTasks={() => activeEvent?.slug && navigate(adminPath(`/mobile/events/${activeEvent.slug}/tasks`))}
        onShowQr={() => activeEvent?.slug && navigate(adminPath(`/mobile/events/${activeEvent.slug}/qr`))}
      />

      <SecondaryGrid
        event={activeEvent}
        onGuests={() => activeEvent?.slug && navigate(adminPath(`/mobile/events/${activeEvent.slug}/members`))}
        onPrint={() => activeEvent?.slug && navigate(adminPath(`/mobile/events/${activeEvent.slug}/qr`))}
        onInvites={() => activeEvent?.slug && navigate(adminPath(`/mobile/events/${activeEvent.slug}/members`))}
        onSettings={() => activeEvent?.slug && navigate(adminPath(`/mobile/events/${activeEvent.slug}`))}
      />

      <KpiStrip
        event={activeEvent}
        stats={stats}
        loading={statsLoading}
        locale={locale}
        tasksEnabled={tasksEnabled}
      />

      <AlertsAndHints event={activeEvent} stats={stats} tasksEnabled={tasksEnabled} />
      {tourSheet}
      {packageSummarySheet}
    </MobileShell>
  );
}

function PackageSummarySheet({
  open,
  onClose,
  onContinue,
  packageName,
  remainingEvents,
  purchasedAt,
  expiresAt,
  limits,
  features,
  locale,
}: {
  open: boolean;
  onClose: () => void;
  onContinue: () => void;
  packageName: string;
  remainingEvents: number | null | undefined;
  purchasedAt: string | null | undefined;
  expiresAt: string | null | undefined;
  limits: Record<string, unknown> | null;
  features: string[] | null;
  locale: string;
}) {
  const { t } = useTranslation('management');
  const { textStrong, muted, border, surface, accentSoft, primary } = useAdminTheme();
  const text = textStrong;
  const resolvedFeatures = collectPackageFeatures({
    features,
    package_limits: limits,
    branding_allowed: (limits as any)?.branding_allowed ?? null,
    watermark_allowed: (limits as any)?.watermark_allowed ?? null,
  } as any);
  const limitEntries = getPackageLimitEntries(limits, t, { remainingEvents });
  const hasFeatures = resolvedFeatures.length > 0;

  const formatDate = (value?: string | null) => formatEventDate(value, locale) ?? t('mobileDashboard.packageSummary.unknown', 'Unknown');

  return (
    <MobileSheet open={open} title={t('mobileDashboard.packageSummary.title', 'Your package summary')} onClose={onClose}>
      <YStack space="$3">
        <MobileCard space="$2.5" borderColor={border} backgroundColor={surface}>
          <YStack space="$1.5">
            <Text fontSize="$sm" fontWeight="800" color={text}>
              {packageName}
            </Text>
            <Text fontSize="$xs" color={muted}>
              {t('mobileDashboard.packageSummary.subtitle', 'Here is a quick overview of your active package.')}
            </Text>
          </YStack>
          <YStack space="$2" marginTop="$2">
            <SummaryRow
              label={t('mobileDashboard.packageSummary.remaining', 'Remaining events')}
              value={formatPackageLimit(remainingEvents, t)}
            />
            <SummaryRow label={t('mobileDashboard.packageSummary.purchased', 'Purchased')} value={formatDate(purchasedAt)} />
            {expiresAt ? (
              <SummaryRow label={t('mobileDashboard.packageSummary.expires', 'Expires')} value={formatDate(expiresAt)} />
            ) : null}
          </YStack>
        </MobileCard>

        {limitEntries.length ? (
          <MobileCard space="$2" borderColor={border} backgroundColor={surface}>
            <Text fontSize="$sm" fontWeight="800" color={text}>
              {t('mobileDashboard.packageSummary.limitsTitle', 'Limits')}
            </Text>
            <YStack space="$1.5" marginTop="$2">
              {limitEntries.map((entry) => (
                <SummaryRow key={entry.key} label={entry.label} value={entry.value} />
              ))}
            </YStack>
          </MobileCard>
        ) : null}

        {hasFeatures ? (
          <MobileCard space="$2" borderColor={border} backgroundColor={surface}>
            <Text fontSize="$sm" fontWeight="800" color={text}>
              {t('mobileDashboard.packageSummary.featuresTitle', 'Included features')}
            </Text>
            <YStack space="$1.5" marginTop="$2">
              {resolvedFeatures.map((feature) => (
                <XStack key={feature} alignItems="center" space="$2">
                  <XStack width={24} height={24} borderRadius={8} backgroundColor={accentSoft} alignItems="center" justifyContent="center">
                    <Sparkles size={14} color={primary} />
                  </XStack>
                  <Text fontSize="$xs" color={text}>
                    {getPackageFeatureLabel(feature, t)}
                  </Text>
                </XStack>
              ))}
            </YStack>
          </MobileCard>
        ) : null}

        <MobileCard space="$2" borderColor={border} backgroundColor={surface}>
          <Text fontSize="$xs" color={muted}>
            {t('mobileDashboard.packageSummary.hint', 'You can revisit billing any time to review or upgrade your package.')}
          </Text>
        </MobileCard>

        <XStack space="$2">
          <CTAButton label={t('mobileDashboard.packageSummary.continue', 'Continue to event setup')} onPress={onContinue} fullWidth={false} />
          <CTAButton label={t('mobileDashboard.packageSummary.dismiss', 'Close')} tone="ghost" onPress={onClose} fullWidth={false} />
        </XStack>
      </YStack>
    </MobileSheet>
  );
}

function SummaryRow({ label, value }: { label: string; value: string }) {
  const { textStrong, muted } = useAdminTheme();
  return (
    <XStack alignItems="center" justifyContent="space-between">
      <Text fontSize="$xs" color={textStrong}>
        {label}
      </Text>
      <Text fontSize="$xs" color={muted}>
        {value}
      </Text>
    </XStack>
  );
}

function PackageSummaryBanner({
  packageName,
  onOpen,
}: {
  packageName?: string | null;
  onOpen: () => void;
}) {
  const { t } = useTranslation('management');
  const { textStrong, muted, border, surface, accentSoft, primary } = useAdminTheme();
  const text = textStrong;

  return (
    <MobileCard space="$2" borderColor={border} backgroundColor={surface}>
      <XStack alignItems="center" justifyContent="space-between" gap="$2">
        <XStack alignItems="center" space="$2" flex={1}>
          <XStack
            width={36}
            height={36}
            borderRadius={12}
            backgroundColor={accentSoft}
            alignItems="center"
            justifyContent="center"
          >
            <Sparkles size={16} color={primary} />
          </XStack>
          <YStack space="$0.5" flex={1}>
            <Text fontSize="$sm" fontWeight="800" color={text}>
              {t('mobileDashboard.packageSummary.bannerTitle', 'Your package summary')}
            </Text>
            <Text fontSize="$xs" color={muted}>
              {t('mobileDashboard.packageSummary.bannerSubtitle', {
                name: packageName ?? t('mobileDashboard.packageSummary.fallbackTitle', 'Package summary'),
                defaultValue: '{{name}} is active. Review limits & features.',
              })}
            </Text>
          </YStack>
        </XStack>
        <CTAButton
          label={t('mobileDashboard.packageSummary.bannerCta', 'View')}
          tone="ghost"
          fullWidth={false}
          onPress={onOpen}
        />
      </XStack>
    </MobileCard>
  );
}

function DeviceSetupCard({ installPrompt, pushState, devicePermissions, onOpenSettings }: DeviceSetupProps) {
  const { t } = useTranslation('management');
  const { textStrong, muted, border, primary, accentSoft } = useAdminTheme();
  const text = textStrong;
  const accent = primary;
  const iconBg = accentSoft;
  const iconColor = primary;

  const items: Array<{
    key: string;
    icon: React.ComponentType<{ size?: number; color?: string }>;
    title: string;
    description: string;
    badge: string;
    badgeTone: 'success' | 'warning' | 'muted';
    actionLabel?: string;
    action?: () => void;
    actionDisabled?: boolean;
  }> = [];

  const showInstall = !installPrompt.isInstalled && (installPrompt.canInstall || installPrompt.isIos);
  if (showInstall) {
    items.push({
      key: 'install',
      icon: Smartphone,
      title: t('mobileDashboard.setup.installTitle', 'Install app'),
      description: installPrompt.isIos
        ? t('mobileDashboard.setup.installIosHint', 'On iOS: Share → Add to Home Screen.')
        : t('mobileDashboard.setup.installDescription', 'Get full-screen access and faster launch.'),
      badge: installPrompt.canInstall
        ? t('mobileDashboard.setup.installReady', 'Ready')
        : t('mobileDashboard.setup.installManual', 'Manual'),
      badgeTone: installPrompt.canInstall ? 'warning' : 'muted',
      actionLabel: installPrompt.canInstall ? t('mobileDashboard.setup.installAction', 'Install now') : undefined,
      action: installPrompt.canInstall ? () => void installPrompt.promptInstall() : undefined,
      actionDisabled: !installPrompt.canInstall,
    });
  }

  if (pushState.supported && !pushState.subscribed) {
    const pushBlocked = pushState.permission === 'denied';
    items.push({
      key: 'push',
      icon: Bell,
      title: t('mobileDashboard.setup.pushTitle', 'Enable push notifications'),
      description: pushBlocked
        ? t('mobileDashboard.setup.pushBlockedDesc', 'Notifications are blocked in the browser settings.')
        : t('mobileDashboard.setup.pushDescription', 'Stay on top of uploads and quota alerts.'),
      badge: pushBlocked
        ? t('mobileDashboard.setup.pushBlocked', 'Blocked')
        : t('mobileDashboard.setup.pushOff', 'Off'),
      badgeTone: 'warning',
      actionLabel: pushBlocked
        ? t('mobileDashboard.setup.pushSettings', 'Open settings')
        : t('mobileDashboard.setup.pushAction', 'Enable push'),
      action: pushBlocked ? onOpenSettings : () => void pushState.enable(),
      actionDisabled: pushState.loading,
    });
  }

  if (devicePermissions.storage === 'available') {
    items.push({
      key: 'storage',
      icon: ShieldCheck,
      title: t('mobileDashboard.setup.storageTitle', 'Protect offline data'),
      description: t('mobileDashboard.setup.storageDescription', 'Keep cached uploads available when you go offline.'),
      badge: t('mobileDashboard.setup.storageUnprotected', 'Not protected'),
      badgeTone: 'warning',
      actionLabel: t('mobileDashboard.setup.storageAction', 'Protect now'),
      action: () => void devicePermissions.requestPersistentStorage(),
      actionDisabled: devicePermissions.loading,
    });
  }

  if (items.length === 0) {
    return null;
  }

  return (
    <MobileCard space="$3" borderColor={border}>
      <XStack alignItems="center" justifyContent="space-between">
        <YStack space="$0.5">
          <Text fontSize="$sm" fontWeight="800" color={text}>
            {t('mobileDashboard.setupTitle', 'Set up this device')}
          </Text>
          <Text fontSize="$xs" color={muted}>
            {t('mobileDashboard.setupSubtitle', 'Finish these steps for the best mobile experience.')}
          </Text>
        </YStack>
        <Download size={18} color={accent} />
      </XStack>
      <YStack space="$2">
        {items.map((item) => (
          <YStack key={item.key} space="$1.5" padding="$2" borderRadius={12} borderWidth={1} borderColor={`${border}aa`}>
            <XStack alignItems="center" justifyContent="space-between" gap="$2">
              <XStack alignItems="center" space="$2" flex={1}>
                <XStack
                  width={32}
                  height={32}
                  borderRadius={10}
                  backgroundColor={iconBg}
                  alignItems="center"
                  justifyContent="center"
                >
                  <item.icon size={16} color={iconColor} />
                </XStack>
                <YStack flex={1} space="$0.5">
                  <Text fontSize="$sm" fontWeight="700" color={text}>
                    {item.title}
                  </Text>
                  <Text fontSize="$xs" color={muted}>
                    {item.description}
                  </Text>
                </YStack>
              </XStack>
              <PillBadge tone={item.badgeTone}>{item.badge}</PillBadge>
            </XStack>
            {item.actionLabel && item.action ? (
              <Pressable onPress={item.action} disabled={item.actionDisabled}>
                <Text
                  fontSize="$xs"
                  fontWeight="700"
                  color={item.actionDisabled ? muted : accent}
                  textDecorationLine="underline"
                >
                  {item.actionLabel}
                </Text>
              </Pressable>
            ) : null}
          </YStack>
        ))}
      </YStack>
    </MobileCard>
  );
}

function OnboardingEmptyState({ installPrompt, pushState, devicePermissions, onOpenSettings }: DeviceSetupProps) {
  const { t } = useTranslation('management');
  const navigate = useNavigate();
  const { textStrong, muted, border, accentSoft, accentStrong, surfaceMuted, primary, shadow } = useAdminTheme();
  const text = textStrong;
  const accent = primary;
  const stepBg = surfaceMuted;
  const stepBorder = border;
  const supportBg = surfaceMuted;
  const supportBorder = border;

  const steps = [
    t('mobileDashboard.emptyStepDetails', 'Add name & date'),
    t('mobileDashboard.emptyStepQr', 'Share your QR poster'),
    t('mobileDashboard.emptyStepReview', 'Review first uploads'),
  ];

  const previews = [
    {
      icon: QrCode,
      title: t('mobileDashboard.emptyPreviewQr', 'Share QR poster'),
      desc: t('mobileDashboard.emptyPreviewQrDesc', 'Print-ready codes for guests and crew.'),
    },
    {
      icon: ImageIcon,
      title: t('mobileDashboard.emptyPreviewGallery', 'Gallery & highlights'),
      desc: t('mobileDashboard.emptyPreviewGalleryDesc', 'Moderate uploads, feature the best moments.'),
    },
    {
      icon: ListTodo,
      title: t('mobileDashboard.emptyPreviewTasks', 'Tasks & challenges'),
      desc: t('mobileDashboard.emptyPreviewTasksDesc', 'Guide guests with playful prompts.'),
    },
  ];

  return (
    <YStack space="$3">
      <DeviceSetupCard
        installPrompt={installPrompt}
        pushState={pushState}
        devicePermissions={devicePermissions}
        onOpenSettings={onOpenSettings}
      />
      <MobileCard
        padding="$4"
        borderColor="transparent"
        overflow="hidden"
        backgroundColor="linear-gradient(140deg, rgba(14,165,233,0.16), rgba(79,70,229,0.22))"
      >
        <YStack position="absolute" top={-10} right={-10} opacity={0.16} scale={1.2}>
          <Sparkles size={72} color={accentStrong} />
        </YStack>
        <YStack position="absolute" bottom={-14} left={-8} opacity={0.14}>
          <QrCode size={96} color={accentStrong} />
        </YStack>
        <YStack space="$2" zIndex={1}>
          <PillBadge tone="muted">{t('mobileDashboard.emptyBadge', 'Welcome aboard')}</PillBadge>
          <Text fontSize="$xl" fontWeight="900" color={text}>
            {t('mobileDashboard.emptyTitle', "Welcome! Let's launch your first event")}
          </Text>
          <Text fontSize="$sm" color={text} opacity={0.9}>
            {t('mobileDashboard.emptyBody', 'Print a QR, collect uploads, and start moderating in minutes.')}
          </Text>
          <CTAButton label={t('mobileDashboard.ctaCreate', 'Create event')} onPress={() => navigate(adminPath('/mobile/events/new'))} />
          <CTAButton
            label={t('mobileDashboard.ctaWelcome', 'Start welcome journey')}
            tone="ghost"
            onPress={() => navigate(ADMIN_WELCOME_BASE_PATH)}
          />
        </YStack>
      </MobileCard>

      <MobileCard space="$2.5" borderColor={border} backgroundColor={stepBg}>
        <XStack alignItems="center" justifyContent="space-between">
          <Text fontSize="$sm" fontWeight="800" color={text}>
            {t('mobileDashboard.emptyChecklistTitle', 'Quick steps to go live')}
          </Text>
          <PillBadge tone="muted">
            {t('mobileDashboard.emptyChecklistProgress', '{{done}}/{{total}} steps', { done: 0, total: steps.length })}
          </PillBadge>
        </XStack>
        <YStack space="$2">
          {steps.map((label) => (
            <XStack
              key={label}
              alignItems="center"
              space="$2"
              padding="$2"
              borderRadius={12}
              backgroundColor="rgba(255,255,255,0.5)"
              borderWidth={1}
              borderColor={stepBorder}
            >
              <XStack
                width={34}
                height={34}
                borderRadius={12}
                alignItems="center"
                justifyContent="center"
                backgroundColor={accentSoft}
                borderWidth={1}
                borderColor={`${accentStrong}33`}
              >
                <CheckCircle2 size={18} color={accent} />
              </XStack>
              <Text fontSize="$sm" color={text} flex={1}>
                {label}
              </Text>
            </XStack>
          ))}
        </YStack>
      </MobileCard>

      <MobileCard space="$2" borderColor={border}>
        <Text fontSize="$sm" fontWeight="800" color={text}>
          {t('mobileDashboard.emptyPreviewTitle', "Here's what awaits")}
        </Text>
        <XStack space="$2" flexWrap="wrap">
          {previews.map(({ icon: Icon, title, desc }) => (
            <YStack
              key={title}
              width="48%"
              minWidth={160}
              space="$1.5"
              padding="$3"
              borderRadius={14}
              borderWidth={1}
              borderColor={`${border}aa`}
              backgroundColor="rgba(255,255,255,0.6)"
              shadowColor={shadow}
              shadowOpacity={0.04}
              shadowRadius={10}
              shadowOffset={{ width: 0, height: 6 }}
            >
              <XStack
                width={36}
                height={36}
                borderRadius={12}
                backgroundColor={accentSoft}
                alignItems="center"
                justifyContent="center"
              >
                <Icon size={18} color={accent} />
              </XStack>
              <Text fontSize="$sm" fontWeight="700" color={text}>
                {title}
              </Text>
              <Text fontSize="$xs" color={muted}>
                {desc}
              </Text>
            </YStack>
          ))}
        </XStack>
      </MobileCard>

      <MobileCard space="$2" backgroundColor={supportBg} borderColor={supportBorder}>
        <XStack alignItems="center" space="$2">
          <XStack
            width={36}
            height={36}
            borderRadius={12}
            backgroundColor={accentSoft}
            alignItems="center"
            justifyContent="center"
          >
            <MessageCircle size={18} color={accent} />
          </XStack>
          <YStack space="$0.5">
            <Text fontSize="$sm" fontWeight="800" color={text}>
              {t('mobileDashboard.emptySupportTitle', 'Need help?')}
            </Text>
            <Text fontSize="$xs" color={muted}>
              {t('mobileDashboard.emptySupportBody', 'We are here if you need a hand getting started.')}
            </Text>
          </YStack>
        </XStack>
        <XStack space="$3">
          <Text fontSize="$xs" color={accent} textDecorationLine="underline">
            {t('mobileDashboard.emptySupportDocs', 'Docs: Getting started')}
          </Text>
          <Text fontSize="$xs" color={accent} textDecorationLine="underline">
            {t('mobileDashboard.emptySupportEmail', 'Email support')}
          </Text>
        </XStack>
      </MobileCard>
    </YStack>
  );
}

function EventPickerList({ events, locale, text, muted, border }: { events: TenantEvent[]; locale: string; text: string; muted: string; border: string }) {
  const { t } = useTranslation('management');
  const { selectEvent } = useEventContext();
  const navigate = useNavigate();
  const [localEvents, setLocalEvents] = React.useState<TenantEvent[]>(events);
  const [loading, setLoading] = React.useState(false);

  React.useEffect(() => {
    setLocalEvents(events);
  }, [events]);

  React.useEffect(() => {
    if (events.length > 0 || loading) {
      return;
    }
    setLoading(true);
    getEvents({ force: true })
      .then((list) => setLocalEvents(list ?? []))
      .catch(() => setLocalEvents([]))
      .finally(() => setLoading(false));
  }, [events.length, loading]);

  return (
    <YStack space="$2">
      <Text fontSize="$sm" color={text} fontWeight="700">
        {t('mobileDashboard.pickEvent', 'Select an event')}
      </Text>
      {localEvents.map((event) => (
        <Pressable
          key={event.slug}
          onPress={() => {
            selectEvent(event.slug ?? null);
            if (event.slug) {
              navigate(adminPath(`/mobile/events/${event.slug}`));
            }
          }}
        >
          <MobileCard borderColor={border} space="$2">
            <XStack alignItems="center" justifyContent="space-between">
              <YStack space="$1">
                <Text fontSize="$md" fontWeight="800" color={text}>
                  {resolveEventDisplayName(event)}
                </Text>
                <Text fontSize="$xs" color={muted}>
                  {formatEventDate(event.event_date, locale) ?? t('mobileDashboard.status.draft', 'Draft')}
                </Text>
              </YStack>
              <PillBadge tone={event.status === 'published' ? 'success' : 'warning'}>
                {event.status === 'published'
                  ? t('mobileDashboard.status.published', 'Live')
                  : t('mobileDashboard.status.draft', 'Draft')}
              </PillBadge>
            </XStack>
          </MobileCard>
        </Pressable>
      ))}
    </YStack>
  );
}

function FeaturedActions({
  tasksEnabled,
  onReviewPhotos,
  onManageTasks,
  onShowQr,
}: {
  tasksEnabled: boolean;
  onReviewPhotos: () => void;
  onManageTasks: () => void;
  onShowQr: () => void;
}) {
  const { t } = useTranslation('management');
  const { textStrong, muted, subtle } = useAdminTheme();
  const text = textStrong;
  const cards = [
    {
      key: 'photos',
      label: t('mobileDashboard.photosLabel', 'Review photos'),
      desc: t('mobileDashboard.photosDesc', 'Moderate uploads and highlights'),
      icon: ImageIcon,
      color: ADMIN_ACTION_COLORS.images,
      action: onReviewPhotos,
    },
    {
      key: 'tasks',
      label: t('mobileDashboard.tasksLabel', 'Manage tasks & challenges'),
      desc: tasksEnabled
        ? t('mobileDashboard.tasksDesc', 'Assign and track progress')
        : t('mobileDashboard.tasksDisabledDesc', 'Guests do not see tasks (task mode off)'),
      icon: ListTodo,
      color: ADMIN_ACTION_COLORS.tasks,
      action: onManageTasks,
    },
    {
      key: 'qr',
      label: t('mobileDashboard.qrLabel', 'Show / share QR code'),
      desc: t('mobileDashboard.qrDesc', 'Posters, cards, and links'),
      icon: QrCode,
      color: ADMIN_ACTION_COLORS.qr,
      action: onShowQr,
    },
  ];

  return (
    <YStack space="$2">
      {cards.map((card) => (
        <Pressable key={card.key} onPress={card.action}>
          <MobileCard borderColor={`${card.color}44`} backgroundColor={`${card.color}0f`} space="$2.5">
            <XStack alignItems="center" space="$3">
              <XStack width={44} height={44} borderRadius={14} backgroundColor={card.color} alignItems="center" justifyContent="center">
                <card.icon size={20} color="white" />
              </XStack>
              <YStack space="$1" flex={1}>
                <Text fontSize="$md" fontWeight="800" color={text}>
                  {card.label}
                </Text>
                <Text fontSize="$xs" color={muted}>
                  {card.desc}
                </Text>
              </YStack>
              <Text fontSize="$xl" color={subtle}>
                ˃
              </Text>
            </XStack>
          </MobileCard>
        </Pressable>
      ))}
    </YStack>
  );
}

function SecondaryGrid({
  event,
  onGuests,
  onPrint,
  onInvites,
  onSettings,
}: {
  event: TenantEvent | null;
  onGuests: () => void;
  onPrint: () => void;
  onInvites: () => void;
  onSettings: () => void;
}) {
  const { t } = useTranslation('management');
  const { textStrong, muted, border, surface, accentSoft, primary } = useAdminTheme();
  const text = textStrong;
  const brandingAllowed = isBrandingAllowed(event ?? null);
  const tiles = [
    {
      icon: Users,
      label: t('mobileDashboard.shortcutGuests', 'Guest management'),
      color: ADMIN_ACTION_COLORS.guests,
      action: onGuests,
    },
    {
      icon: QrCode,
      label: t('mobileDashboard.shortcutPrints', 'Print & poster downloads'),
      color: ADMIN_ACTION_COLORS.qr,
      action: onPrint,
    },
    {
      icon: Sparkles,
      label: t('mobileDashboard.shortcutInvites', 'Team / helper invites'),
      color: ADMIN_ACTION_COLORS.invites,
      action: onInvites,
    },
    {
      icon: Settings,
      label: t('mobileDashboard.shortcutSettings', 'Event settings'),
      color: ADMIN_ACTION_COLORS.success,
      action: onSettings,
    },
    {
      icon: Sparkles,
      label: t('mobileDashboard.shortcutBranding', 'Branding & moderation'),
      color: ADMIN_ACTION_COLORS.branding,
      action: brandingAllowed ? onSettings : undefined,
      disabled: !brandingAllowed,
    },
  ];

  return (
    <YStack space="$2" marginTop="$2">
      <Text fontSize="$sm" fontWeight="800" color={text}>
        {t('mobileDashboard.shortcutsTitle', 'Shortcuts')}
      </Text>
      <XStack flexWrap="wrap" space="$2">
        {tiles.map((tile, index) => (
          <ActionTile
            key={tile.label}
            icon={tile.icon}
            label={tile.label}
            color={tile.color}
            onPress={tile.action}
            disabled={tile.disabled}
            delayMs={index * ADMIN_MOTION.tileStaggerMs}
          />
        ))}
      </XStack>
      {event ? (
        <MobileCard backgroundColor={surface} borderColor={border} space="$1.5">
          <Text fontSize="$sm" fontWeight="700" color={text}>
            {resolveEventDisplayName(event)}
          </Text>
          <Text fontSize="$xs" color={muted}>
            {renderEventLocation(event)}
          </Text>
        </MobileCard>
      ) : null}
    </YStack>
  );
}

function KpiStrip({
  event,
  stats,
  loading,
  locale,
  tasksEnabled,
}: {
  event: TenantEvent | null;
  stats: EventStats | null | undefined;
  loading: boolean;
  locale: string;
  tasksEnabled: boolean;
}) {
  const { t } = useTranslation('management');
  const { textStrong, muted } = useAdminTheme();
  const text = textStrong;
  if (!event) return null;

  const kpis = [
    {
      label: t('mobileDashboard.kpiPhotos', 'Photos'),
      value: stats?.uploads_total ?? event.photo_count ?? '—',
      icon: ImageIcon,
    },
    {
      label: t('mobileDashboard.kpiGuests', 'Guests'),
      value: event.active_invites_count ?? event.total_invites_count ?? '—',
      icon: Users,
    },
  ];

  if (tasksEnabled) {
    kpis.unshift({
      label: t('mobileDashboard.kpiTasks', 'Open tasks'),
      value: event.tasks_count ?? '—',
      icon: ListTodo,
    });
  }

  return (
    <YStack space="$2">
      <Text fontSize="$sm" fontWeight="800" color={text}>
        {t('mobileDashboard.kpiTitle', 'Key performance indicators')}
      </Text>
      {loading ? (
        <XStack space="$2" flexWrap="wrap">
          {Array.from({ length: 3 }).map((_, idx) => (
            <MobileCard key={`kpi-${idx}`} height={90} width="32%" />
          ))}
        </XStack>
      ) : (
        <XStack space="$2" flexWrap="wrap">
          {kpis.map((kpi) => (
            <KpiTile key={kpi.label} icon={kpi.icon} label={kpi.label} value={kpi.value ?? '—'} />
          ))}
        </XStack>
      )}
      <Text fontSize="$xs" color={muted}>
        {formatEventDate(event.event_date, locale) ?? ''}
      </Text>
    </YStack>
  );
}

function AlertsAndHints({ event, stats, tasksEnabled }: { event: TenantEvent | null; stats: EventStats | null | undefined; tasksEnabled: boolean }) {
  const { t } = useTranslation('management');
  const { textStrong, warningBg, warningBorder, warningText } = useAdminTheme();
  const text = textStrong;
  if (!event) return null;

  const alerts: string[] = [];
  if (stats?.pending_photos) {
    alerts.push(t('mobileDashboard.alertPending', '{{count}} new uploads awaiting moderation', { count: stats.pending_photos }));
  }
  if (tasksEnabled && event.tasks_count) {
    alerts.push(t('mobileDashboard.alertTasks', '{{count}} tasks due or open', { count: event.tasks_count }));
  }

  if (alerts.length === 0) {
    return null;
  }

  return (
    <YStack space="$1.5">
      <Text fontSize="$sm" fontWeight="800" color={text}>
        {t('mobileDashboard.alertsTitle', 'Alerts')}
      </Text>
      {alerts.map((alert) => (
        <MobileCard key={alert} backgroundColor={warningBg} borderColor={warningBorder} space="$2">
          <Text fontSize="$sm" color={warningText}>
            {alert}
          </Text>
        </MobileCard>
      ))}
    </YStack>
  );
}
