import React from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { RefreshCcw, Plus, Pencil, Trash2, ChevronDown, ChevronRight, Check, Info } from 'lucide-react';
import { Card } from '@tamagui/card';
import { YStack, XStack } from '@tamagui/stacks';
import { YGroup } from '@tamagui/group';
import { SizableText as Text } from '@tamagui/text';
import { ListItem } from '@tamagui/list-item';
import { Pressable } from '@tamagui/react-native-web-lite';
import { Button } from '@tamagui/button';
import { AlertDialog } from '@tamagui/alert-dialog';
import { Switch } from '@tamagui/switch';
import { Checkbox } from '@tamagui/checkbox';
import { Tabs } from 'tamagui';
import { MobileShell, HeaderActionButton } from './components/MobileShell';
import { MobileCard, CTAButton, SkeletonCard, FloatingActionButton, PillBadge } from './components/Primitives';
import { MobileField, MobileInput, MobileSelect, MobileTextArea } from './components/FormControls';
import {
  getEvent,
  getEvents,
  getEventTasks,
  updateEvent,
  updateTask,
  TenantTask,
  TenantEvent,
  assignTasksToEvent,
  getTasks,
  getTaskCollections,
  importTaskCollection,
  createTask,
  TenantTaskCollection,
  getEmotions,
  TenantEmotion,
  detachTasksFromEvent,
  createEmotion,
  updateEmotion as updateEmotionApi,
  deleteEmotion as deleteEmotionApi,
} from '../api';
import { adminPath } from '../constants';
import { isAuthError } from '../auth/tokens';
import { getApiErrorMessage } from '../lib/apiError';
import toast from 'react-hot-toast';
import { MobileSheet } from './components/Sheet';
import { Tag } from './components/Tag';
import { useEventContext } from '../context/EventContext';
import { RadioGroup } from '@tamagui/radio-group';
import { useBackNavigation } from './hooks/useBackNavigation';
import { type TaskSectionKey } from './lib/taskSectionCounts';
import { withAlpha } from './components/colors';
import { useAdminTheme } from './theme';
import { resolveEngagementMode } from '../lib/events';
import { useAuth } from '../auth/context';
import { ContextHelpLink } from './components/ContextHelpLink';

function allowPermission(permissions: string[], permission: string): boolean {
  if (permissions.includes('*') || permissions.includes(permission)) {
    return true;
  }
  if (permission.includes(':')) {
    const [prefix] = permission.split(':');
    return permissions.includes(`${prefix}:*`);
  }
  return false;
}

export default function MobileEventTasksPage() {
  const { slug: slugParam } = useParams<{ slug?: string }>();
  const { activeEvent, selectEvent } = useEventContext();
  const slug = slugParam ?? activeEvent?.slug ?? null;
  const navigate = useNavigate();
  const { t } = useTranslation('management');
  const { user } = useAuth();
  const {
    textStrong,
    muted,
    subtle,
    border,
    primary,
    danger,
    surface,
    surfaceMuted,
    dangerBg,
    dangerText,
    overlay,
    shadow,
    glassSurface,
    glassBorder,
    glassShadow,
  } = useAdminTheme();
  const isMember = user?.role === 'member';
  const [assignedTasks, setAssignedTasks] = React.useState<TenantTask[]>([]);
  const [library, setLibrary] = React.useState<TenantTask[]>([]);
  const [collections, setCollections] = React.useState<TenantTaskCollection[]>([]);
  const [emotions, setEmotions] = React.useState<TenantEmotion[]>([]);
  const [activeTab, setActiveTab] = React.useState<TaskSectionKey>('assigned');
  const [showTaskSheet, setShowTaskSheet] = React.useState(false);
  const [newTask, setNewTask] = React.useState({
    id: null as number | null,
    title: '',
    description: '',
    emotion_id: '' as string | '',
    tenant_id: null as number | null,
  });
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState<string | null>(null);
  const [busyId, setBusyId] = React.useState<number | null>(null);
  const [assigningId, setAssigningId] = React.useState<number | null>(null);
  const [deleteCandidate, setDeleteCandidate] = React.useState<TenantTask | null>(null);
  const [eventId, setEventId] = React.useState<number | null>(null);
  const [searchTerm, setSearchTerm] = React.useState('');
  const [emotionFilter, setEmotionFilter] = React.useState<string>('');
  const [expandedLibrary, setExpandedLibrary] = React.useState(false);
  const [expandedCollections, setExpandedCollections] = React.useState(false);
  const [selectionMode, setSelectionMode] = React.useState(false);
  const [selectedTaskIds, setSelectedTaskIds] = React.useState<Set<number>>(new Set());
  const [bulkDeleteOpen, setBulkDeleteOpen] = React.useState(false);
  const [bulkDeleteBusy, setBulkDeleteBusy] = React.useState(false);
  const longPressTimer = React.useRef<number | null>(null);
  const longPressTriggered = React.useRef(false);
  const [showFabMenu, setShowFabMenu] = React.useState(false);
  const [showBulkSheet, setShowBulkSheet] = React.useState(false);
  const [bulkLines, setBulkLines] = React.useState('');
  const [showEmotionSheet, setShowEmotionSheet] = React.useState(false);
  const [editingEmotion, setEditingEmotion] = React.useState<TenantEmotion | null>(null);
  const [emotionForm, setEmotionForm] = React.useState({ name: '', color: String(border) });
  const [savingEmotion, setSavingEmotion] = React.useState(false);
  const [showEmotionFilterSheet, setShowEmotionFilterSheet] = React.useState(false);
  const [showTaskDetails, setShowTaskDetails] = React.useState(false);
  const [eventRecord, setEventRecord] = React.useState<TenantEvent | null>(null);
  const [tasksToggleBusy, setTasksToggleBusy] = React.useState(false);
  const text = textStrong;
  const back = useBackNavigation(slug ? adminPath(`/mobile/events/${slug}`) : adminPath('/mobile/events'));
  const permissionSource = eventRecord ?? activeEvent;
  const memberPermissions = Array.isArray(permissionSource?.member_permissions) ? permissionSource?.member_permissions ?? [] : [];
  const canManageTasks = React.useMemo(
    () => (isMember ? allowPermission(memberPermissions, 'tasks:manage') : true),
    [isMember, memberPermissions]
  );
  const tasksEnabled = resolveEngagementMode(permissionSource ?? null) !== 'photo_only';
  const maxTasks = React.useMemo(() => {
    const limit = eventRecord?.limits?.tasks?.limit;
    return typeof limit === 'number' && Number.isFinite(limit) ? limit : null;
  }, [eventRecord?.limits?.tasks?.limit]);
  const remainingTasks = React.useMemo(() => {
    const remaining = eventRecord?.limits?.tasks?.remaining;
    if (typeof remaining === 'number' && Number.isFinite(remaining)) {
      return Math.max(0, remaining);
    }
    if (maxTasks === null) {
      return null;
    }
    return Math.max(0, maxTasks - assignedTasks.length);
  }, [assignedTasks.length, eventRecord?.limits?.tasks?.remaining, maxTasks]);
  const canAddTasks = maxTasks === null || (remainingTasks ?? 0) > 0;
  const limitReachedMessage = t('events.tasks.limitReached', 'Photo task limit reached.');
  const limitReachedHint =
    maxTasks === null
      ? null
      : t('events.tasks.limitReachedHint', {
          count: maxTasks,
          defaultValue: 'This event allows up to {{count}} photo tasks.',
        });
  React.useEffect(() => {
    if (slugParam && activeEvent?.slug !== slugParam) {
      selectEvent(slugParam);
    }
  }, [slugParam, activeEvent?.slug, selectEvent]);

  // Reset filters when switching events to avoid empty lists due to stale filters.
  React.useEffect(() => {
    setEmotionFilter('');
    setSearchTerm('');
  }, [slug]);

  const load = React.useCallback(async () => {
    if (!slug) {
      try {
        const available = await getEvents({ force: true });
        if (available.length) {
          const target = available[0];
          selectEvent(target.slug ?? null);
          navigate(adminPath(`/mobile/events/${target.slug ?? ''}/tasks`));
          return;
        }
      } catch {
        // ignore
      } finally {
        setError(t('events.errors.missingSlug', 'Kein Event-Slug angegeben.'));
        setLoading(false);
      }
      return;
    }
    setLoading(true);
    setError(null);
    try {
      const event = await getEvent(slug);
      setEventId(event.id);
      setEventRecord(event);
      const eventTypeSlug = event.event_type?.slug ?? null;
      const [result, libraryTasks] = await Promise.all([
        getEventTasks(event.id, 1),
        getTasks({ per_page: 200 }),
      ]);
      const collectionList = await getTaskCollections({
        per_page: 50,
        event_type: eventTypeSlug ?? undefined,
      });
      const emotionList = await getEmotions();
      const assignedIds = new Set(result.data.map((t) => t.id));
      const eventTypeId = event.event_type_id ?? event.event_type?.id ?? null;
      const filteredLibrary = libraryTasks.data.filter((task) => {
        if (assignedIds.has(task.id)) return false;
        if (eventTypeId && task.event_type_id && task.event_type_id !== eventTypeId) return false;
        return true;
      });
      setAssignedTasks(result.data);
      setLibrary(filteredLibrary);
      setCollections(collectionList.data ?? []);
      setEmotions(emotionList ?? []);
      setSelectionMode(false);
      setSelectedTaskIds(new Set());
    } catch (err) {
      if (!isAuthError(err)) {
        const message = getApiErrorMessage(err, t('events.errors.loadFailed', 'Fotoaufgaben konnten nicht geladen werden.'));
        setError(message);
        toast.error(message);
        // If the current slug is invalid, attempt to recover to a valid event to avoid empty lists.
        try {
          const available = await getEvents({ force: true });
          const fallback = available.find((e: TenantEvent) => e.slug !== slug) ?? available[0];
          if (fallback?.slug) {
            selectEvent(fallback.slug);
            navigate(adminPath(`/mobile/events/${fallback.slug}/tasks`));
          }
        } catch {
          // ignore
        }
      }
    } finally {
      setLoading(false);
    }
  }, [slug, t, navigate, selectEvent]);

  React.useEffect(() => {
    void load();
  }, [load]);

  async function quickAssign(taskId: number) {
    if (!eventId) return;
    if (!canAddTasks) {
      toast.error(limitReachedMessage);
      return;
    }
    setAssigningId(taskId);
    try {
      await assignTasksToEvent(eventId, [taskId]);
      const result = await getEventTasks(eventId, 1);
      setAssignedTasks(result.data);
      setLibrary((prev) => prev.filter((t) => t.id !== taskId));
      toast.success(t('events.tasks.assigned', 'Fotoaufgabe hinzugefügt'));
    } catch (err) {
      if (!isAuthError(err)) {
        setError(getApiErrorMessage(err, t('events.errors.saveFailed', 'Fotoaufgabe konnte nicht zugewiesen werden.')));
        toast.error(t('events.tasks.updateFailed', 'Fotoaufgabe konnte nicht zugewiesen werden.'));
      }
    } finally {
      setAssigningId(null);
    }
  }

  async function importCollection(collectionId: number) {
    if (!slug || !eventId) return;
    if (!canAddTasks) {
      toast.error(limitReachedMessage);
      return;
    }
    try {
      await importTaskCollection(collectionId, slug);
      const result = await getEventTasks(eventId, 1);
      const assignedIds = new Set(result.data.map((t) => t.id));
      setAssignedTasks(result.data);
      setLibrary((prev) => prev.filter((t) => !assignedIds.has(t.id)));
      toast.success(t('events.tasks.imported', 'Fotoaufgabenpaket importiert'));
    } catch (err) {
      if (!isAuthError(err)) {
        setError(getApiErrorMessage(err, t('events.errors.saveFailed', 'Paket konnte nicht importiert werden.')));
        toast.error(t('events.errors.saveFailed', 'Paket konnte nicht importiert werden.'));
      }
    }
  }

  async function createNewTask() {
    if (!eventId || !newTask.title.trim()) return;
    if (!canAddTasks) {
      toast.error(limitReachedMessage);
      return;
    }
    try {
      if (newTask.id) {
        if (!Number.isFinite(Number(newTask.id))) {
          toast.error(t('events.tasks.updateFailed', 'Fotoaufgabe konnte nicht gespeichert werden (ID fehlt).'));
          return;
        }

        const isGlobal = !newTask.tenant_id;

        // Global tasks must not be edited in place: clone and replace.
        if (isGlobal) {
          const cloned = await createTask({
            title: newTask.title.trim(),
            description: newTask.description.trim() || null,
            emotion_id: newTask.emotion_id ? Number(newTask.emotion_id) : undefined,
          } as any);
          await assignTasksToEvent(eventId, [cloned.id]);
          await detachTasksFromEvent(eventId, [Number(newTask.id)]);
        } else {
          // Tenant-owned task: update in place.
          await updateTask(Number(newTask.id), {
            id: Number(newTask.id),
            title: newTask.title.trim(),
            description: newTask.description.trim() || null,
            emotion_id: newTask.emotion_id ? Number(newTask.emotion_id) : undefined,
          } as any);
        }
      } else {
        const created = await createTask({
          title: newTask.title.trim(),
          description: newTask.description.trim() || null,
          emotion_id: newTask.emotion_id ? Number(newTask.emotion_id) : undefined,
        } as any);
        await assignTasksToEvent(eventId, [created.id]);
      }
      const result = await getEventTasks(eventId, 1);
      const assignedIds = new Set(result.data.map((t) => t.id));
      setAssignedTasks(result.data);
      setLibrary((prev) => prev.filter((t) => !assignedIds.has(t.id)));
      setShowTaskSheet(false);
      setNewTask({ id: null, title: '', description: '', emotion_id: '', tenant_id: null });
      toast.success(t('events.tasks.created', 'Fotoaufgabe gespeichert'));
    } catch (err) {
      if (!isAuthError(err)) {
        setError(getApiErrorMessage(err, t('events.errors.saveFailed', 'Fotoaufgabe konnte nicht erstellt werden.')));
        toast.error(t('events.errors.saveFailed', 'Fotoaufgabe konnte nicht erstellt werden.'));
      }
    }
  }

  async function detachTask(taskId: number) {
    if (!eventId) return;
    setBusyId(taskId);
    try {
      await detachTasksFromEvent(eventId, [taskId]);
      setAssignedTasks((prev) => prev.filter((task) => task.id !== taskId));
      setSelectedTaskIds((prev) => {
        if (!prev.has(taskId)) return prev;
        const next = new Set(prev);
        next.delete(taskId);
        if (next.size === 0) {
          setSelectionMode(false);
        }
        return next;
      });
      toast.success(t('events.tasks.removed', 'Fotoaufgabe entfernt'));
    } catch (err) {
      if (!isAuthError(err)) {
        setError(getApiErrorMessage(err, t('events.errors.saveFailed', 'Fotoaufgabe konnte nicht entfernt werden.')));
        toast.error(t('events.errors.saveFailed', 'Fotoaufgabe konnte nicht entfernt werden.'));
      }
    } finally {
      setBusyId(null);
    }
  }

  async function confirmDeleteTask() {
    if (!deleteCandidate) return;
    const taskId = deleteCandidate.id;
    setDeleteCandidate(null);
    await detachTask(taskId);
  }

  async function confirmBulkDelete() {
    if (!eventId || selectedTaskIds.size === 0) {
      setBulkDeleteOpen(false);
      return;
    }
    const ids = Array.from(selectedTaskIds);
    setBulkDeleteOpen(false);
    setBulkDeleteBusy(true);
    try {
      await detachTasksFromEvent(eventId, ids);
      setAssignedTasks((prev) => prev.filter((task) => !selectedTaskIds.has(task.id)));
      setSelectedTaskIds(new Set());
      setSelectionMode(false);
      toast.success(t('events.tasks.removed', 'Fotoaufgabe entfernt'));
    } catch (err) {
      if (!isAuthError(err)) {
        toast.error(t('events.errors.saveFailed', 'Fotoaufgabe konnte nicht entfernt werden.'));
      }
    } finally {
      setBulkDeleteBusy(false);
    }
  }

  const startEdit = (task: TenantTask) => {
    setNewTask({
      id: task.id,
      title: task.title,
      description: task.description ?? '',
      emotion_id: task.emotion?.id ? String(task.emotion.id) : '',
      tenant_id: (task as any).tenant_id ?? null,
    });
    setShowTaskSheet(true);
  };

  const filteredTasks = assignedTasks.filter((task) => {
    const matchText =
      !searchTerm ||
      task.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
      (task.description ?? '').toLowerCase().includes(searchTerm.toLowerCase());
    const matchEmotion = !emotionFilter || task.emotion?.id === Number(emotionFilter);
    return matchText && matchEmotion;
  });

  const toggleSelectedTask = React.useCallback((taskId: number) => {
    setSelectedTaskIds((prev) => {
      const next = new Set(prev);
      if (next.has(taskId)) {
        next.delete(taskId);
      } else {
        next.add(taskId);
      }
      if (next.size === 0) {
        setSelectionMode(false);
      }
      return next;
    });
  }, []);

  const clearSelection = React.useCallback(() => {
    setSelectedTaskIds(new Set());
    setSelectionMode(false);
  }, []);

  const startLongPress = React.useCallback(
    (taskId: number) => {
      if (selectionMode) return;
      if (longPressTimer.current) {
        window.clearTimeout(longPressTimer.current);
      }
      longPressTriggered.current = false;
      longPressTimer.current = window.setTimeout(() => {
        longPressTriggered.current = true;
        setSelectionMode(true);
        toggleSelectedTask(taskId);
      }, 450);
    },
    [selectionMode, toggleSelectedTask]
  );

  const cancelLongPress = React.useCallback(() => {
    if (longPressTimer.current) {
      window.clearTimeout(longPressTimer.current);
      longPressTimer.current = null;
    }
  }, []);

  const handleTaskPress = React.useCallback(
    (task: TenantTask) => {
      if (longPressTriggered.current) {
        longPressTriggered.current = false;
        return;
      }
      if (selectionMode) {
        toggleSelectedTask(task.id);
        return;
      }
      startEdit(task);
    },
    [selectionMode, startEdit, toggleSelectedTask]
  );

  React.useEffect(() => {
    return () => cancelLongPress();
  }, [cancelLongPress]);

  async function handleBulkAdd() {
    if (!eventId || !bulkLines.trim()) return;
    if (!canAddTasks) {
      toast.error(limitReachedMessage);
      return;
    }
    const lines = bulkLines
      .split('\n')
      .map((l) => l.trim())
      .filter(Boolean);
    if (!lines.length) return;
    const capacity = remainingTasks === null ? lines.length : Math.max(0, remainingTasks);
    const slicedLines = lines.slice(0, capacity);
    if (!slicedLines.length) {
      toast.error(limitReachedMessage);
      return;
    }
    try {
      if (slicedLines.length < lines.length) {
        toast.error(
          t('events.tasks.limitSkipped', {
            count: lines.length - slicedLines.length,
            defaultValue: 'Skipped {{count}} tasks due to limit.',
          }),
        );
      }

      for (const line of slicedLines) {
        const created = await createTask({ title: line } as any);
        await assignTasksToEvent(eventId, [created.id]);
      }
      const result = await getEventTasks(eventId, 1);
      setAssignedTasks(result.data);
      setBulkLines('');
      setShowBulkSheet(false);
      toast.success(t('events.tasks.created', 'Fotoaufgabe gespeichert'));
    } catch (err) {
      if (!isAuthError(err)) {
        toast.error(t('events.errors.saveFailed', 'Fotoaufgabe konnte nicht erstellt werden.'));
      }
    }
  }

  async function saveEmotion() {
    if (!emotionForm.name.trim()) return;
    setSavingEmotion(true);
    try {
      if (editingEmotion) {
        const updated = await updateEmotionApi(editingEmotion.id, { name: emotionForm.name.trim(), color: emotionForm.color });
        setEmotions((prev) => prev.map((em) => (em.id === editingEmotion.id ? updated : em)));
      } else {
        const created = await createEmotion({ name: emotionForm.name.trim(), color: emotionForm.color });
        setEmotions((prev) => [...prev, created]);
      }
      setShowEmotionSheet(false);
      setEditingEmotion(null);
      setEmotionForm({ name: '', color: border });
      toast.success(t('events.tasks.emotionSaved', 'Emotion gespeichert'));
    } catch (err) {
      if (!isAuthError(err)) {
        toast.error(getApiErrorMessage(err, t('events.errors.saveFailed', 'Konnte nicht gespeichert werden.')));
      }
    } finally {
      setSavingEmotion(false);
    }
  }

  async function removeEmotion(emotionId: number) {
    try {
      await deleteEmotionApi(emotionId);
      setEmotions((prev) => prev.filter((em) => em.id !== emotionId));
      toast.success(t('events.tasks.emotionRemoved', 'Emotion entfernt'));
    } catch (err) {
      if (!isAuthError(err)) {
        toast.error(getApiErrorMessage(err, t('events.errors.saveFailed', 'Konnte nicht gespeichert werden.')));
      }
    }
  }

  async function handleTasksToggle(nextEnabled: boolean) {
    if (!slug || tasksToggleBusy || !canManageTasks) return;
    setTasksToggleBusy(true);
    try {
      const updated = await updateEvent(slug, {
        settings: {
          engagement_mode: nextEnabled ? 'tasks' : 'photo_only',
        },
      });
      setEventRecord(updated);
      toast.success(
        nextEnabled
          ? t('events.tasks.toggle.enabled', 'Photo tasks activated')
          : t('events.tasks.toggle.disabled', 'Photo tasks disabled')
      );
    } catch (err) {
      if (!isAuthError(err)) {
        toast.error(t('events.errors.toggleFailed', 'Status could not be updated.'));
      }
    } finally {
      setTasksToggleBusy(false);
    }
  }

  const taskPanel = assignedTasks.length === 0 ? (
    <YStack space="$2">
      <MobileCard space="$2">
        <Text fontSize={13} fontWeight="700" color={text}>
          {t('events.tasks.emptyTitle', 'No photo tasks yet')}
        </Text>
        <Text fontSize={12} color={muted}>
          {t('events.tasks.emptyBody', 'Create photo tasks or import a pack for your event.')}
        </Text>
        {!canAddTasks ? (
          <Text fontSize={12} fontWeight="600" color={dangerText}>
            {limitReachedMessage}
            {limitReachedHint ? ` ${limitReachedHint}` : ''}
          </Text>
        ) : null}
        <XStack space="$2">
          <CTAButton
            label={t('events.tasks.emptyActionTask', 'Add photo task')}
            onPress={() => setShowTaskSheet(true)}
            disabled={!canAddTasks}
            fullWidth={false}
          />
          <CTAButton
            label={t('events.tasks.emptyActionPack', 'Import photo task pack')}
            tone="ghost"
            onPress={() => setActiveTab('collections')}
            disabled={!canAddTasks}
            fullWidth={false}
          />
        </XStack>
      </MobileCard>
      <YGroup {...({ borderWidth: 1, borderColor: border, borderRadius: "$4", overflow: "hidden" } as any)}>
        <YGroup.Item>
          <ListItem
            hoverTheme
            pressTheme
            onPress={() => {
              if (!canAddTasks) {
                toast.error(limitReachedMessage);
                return;
              }
              setShowTaskSheet(true);
            }}
            title={
              <XStack alignItems="center" space="$2">
                <YStack
                  width={28}
                  height={28}
                  borderRadius={14}
                  backgroundColor={canAddTasks ? primary : withAlpha(border, 0.4)}
                  alignItems="center"
                  justifyContent="center"
                >
                  <Plus size={14} color={canAddTasks ? surface : muted} />
                </YStack>
                <Text fontSize={12.5} fontWeight="700" color={text}>
                  {t('events.tasks.addTask', 'Fotoaufgabe hinzufügen')}
                </Text>
              </XStack>
            }
            subTitle={
              <Text fontSize={11.5} color={muted}>
                {t('events.tasks.addTaskHint', 'Erstelle eine neue Fotoaufgabe für dieses Event.')}
              </Text>
            }
            paddingVertical="$2"
            paddingHorizontal="$3"
            iconAfter={<ChevronRight size={16} color={muted} />}
          />
        </YGroup.Item>
        <YGroup.Item>
          <ListItem
            hoverTheme
            pressTheme
            onPress={() => {
              if (!canAddTasks) {
                toast.error(limitReachedMessage);
                return;
              }
              setActiveTab('collections');
            }}
            title={
              <XStack alignItems="center" space="$2">
                <YStack
                  width={28}
                  height={28}
                  borderRadius={14}
                  backgroundColor={canAddTasks ? primary : withAlpha(border, 0.4)}
                  alignItems="center"
                  justifyContent="center"
                >
                  <Plus size={14} color={canAddTasks ? surface : muted} />
                </YStack>
                <Text fontSize={12.5} fontWeight="700" color={text}>
                  {t('events.tasks.import', 'Fotoaufgabenpaket importieren')}
                </Text>
              </XStack>
            }
            subTitle={
              <Text fontSize={11.5} color={muted}>
                {t('events.tasks.importHint', 'Nutze vordefinierte Pakete für deinen Event-Typ.')}
              </Text>
            }
            paddingVertical="$2"
            paddingHorizontal="$3"
            iconAfter={<ChevronRight size={16} color={muted} />}
          />
        </YGroup.Item>
      </YGroup>
    </YStack>
  ) : (
    <YStack space="$2">
      <XStack alignItems="baseline" justifyContent="space-between" flexWrap="wrap" space="$2">
        <XStack alignItems="baseline" space="$2" flexWrap="wrap">
          <Text fontSize="$sm" fontWeight="800" color={text}>
            {t('events.tasks.assignedTitle', 'Task list')}
          </Text>
          <Text fontSize="$xs" color={muted}>
            {t('events.tasks.count', '{{count}} photo tasks', { count: filteredTasks.length })}
          </Text>
        </XStack>
        {typeof remainingTasks === 'number' && typeof maxTasks === 'number' ? (
          <Tag
            label={t('events.tasks.remainingIndicator', '{{count}} / {{total}} tasks remaining', {
              count: remainingTasks,
              total: maxTasks,
            })}
          />
        ) : null}
      </XStack>
      {selectionMode ? (
        <MobileCard padding="$2.5" space="$2">
          <Text fontSize={12} fontWeight="700" color={text}>
            {t('events.tasks.selectionCount', '{{count}} ausgewählt', { count: selectedTaskIds.size })}
          </Text>
          <XStack space="$2">
            <CTAButton
              label={t('events.tasks.bulkRemove', 'Auswahl löschen')}
              tone="danger"
              fullWidth={false}
              disabled={selectedTaskIds.size === 0 || bulkDeleteBusy}
              onPress={() => setBulkDeleteOpen(true)}
            />
            <CTAButton
              label={t('events.tasks.bulkCancel', 'Auswahl beenden')}
              tone="ghost"
              fullWidth={false}
              onPress={() => clearSelection()}
            />
          </XStack>
        </MobileCard>
      ) : null}
      <YGroup {...({ borderWidth: 1, borderColor: border, borderRadius: "$4", overflow: "hidden" } as any)}>
        {filteredTasks.map((task, idx) => (
          <YGroup.Item key={task.id}>
            <ListItem
              hoverTheme
              pressTheme
              onPress={() => handleTaskPress(task)}
              onPointerDown={() => startLongPress(task.id)}
              onPointerUp={cancelLongPress}
              onPointerLeave={cancelLongPress}
              onPointerCancel={cancelLongPress}
              title={
                <XStack alignItems="center" space="$2">
                  {selectionMode ? (
                    <Checkbox
                      size="$3"
                      checked={selectedTaskIds.has(task.id)}
                      onCheckedChange={() => toggleSelectedTask(task.id)}
                      onPress={(event: any) => event?.stopPropagation?.()}
                      aria-label={t('events.tasks.select', 'Select photo task')}
                    >
                      <Checkbox.Indicator>
                        <Check size={14} color={text} />
                      </Checkbox.Indicator>
                    </Checkbox>
                  ) : null}
                  <Text fontSize={12.5} fontWeight="600" color={text}>
                    {task.title}
                  </Text>
                </XStack>
              }
              subTitle={
                task.description ? (
                  <Text fontSize={11.5} fontWeight="400" color={subtle}>
                    {task.description}
                  </Text>
                ) : null
              }
              iconAfter={
                selectionMode ? null : (
                  <XStack space="$2" alignItems="center">
                    {task.emotion ? (
                      <Tag label={task.emotion.name ?? ''} color={task.emotion.color ?? text} />
                    ) : null}
                    <Button
                      size="$2"
                      circular
                      backgroundColor={dangerBg}
                      borderWidth={1}
                      borderColor={`${danger}33`}
                      icon={<Trash2 size={14} color={dangerText} />}
                      aria-label={t('events.tasks.remove', 'Remove photo task')}
                      disabled={busyId === task.id}
                      onPress={(event: any) => {
                        event?.stopPropagation?.();
                        setDeleteCandidate(task);
                      }}
                    />
                    <ChevronRight size={14} color={subtle} />
                  </XStack>
                )
              }
              paddingVertical="$2"
              paddingHorizontal="$3"
            />
          </YGroup.Item>
        ))}
      </YGroup>
    </YStack>
  );

  const libraryPanel = (
    <YStack space="$2">
      <XStack alignItems="center" justifyContent="space-between" flexWrap="wrap">
        <Text fontSize="$sm" fontWeight="700" color={text}>
          {t('events.tasks.tabs.library', 'Task Library')}
        </Text>
        <Button
          size="$2"
          backgroundColor={withAlpha(primary, 0.12)}
          borderWidth={1}
          borderColor={withAlpha(primary, 0.35)}
          onPress={() => setActiveTab('collections')}
        >
          <Text fontSize="$xs" fontWeight="700" color={primary}>
            {t('events.tasks.import', 'Import photo task pack')}
          </Text>
        </Button>
      </XStack>
      {!canAddTasks ? (
        <Text fontSize={12} fontWeight="600" color={dangerText}>
          {limitReachedMessage}
          {limitReachedHint ? ` ${limitReachedHint}` : ''}
        </Text>
      ) : null}
      {library.length > 6 ? (
        <Pressable onPress={() => setExpandedLibrary((prev) => !prev)}>
          <Text fontSize={12} fontWeight="600" color={primary}>
            {expandedLibrary ? t('events.tasks.hideLibrary', 'Hide library') : t('events.tasks.viewAllLibrary', 'View all')}
          </Text>
        </Pressable>
      ) : null}
      {library.length === 0 ? (
        <Text fontSize={12} fontWeight="500" color={subtle}>
          {t('events.tasks.libraryEmpty', 'No more photo tasks available.')}
        </Text>
      ) : (
        <YGroup {...({ borderWidth: 1, borderColor: border, borderRadius: "$4", overflow: "hidden" } as any)}>
          {(expandedLibrary ? library : library.slice(0, 6)).map((task) => (
            <YGroup.Item key={`lib-${task.id}`}>
              <ListItem
                hoverTheme
                pressTheme
                title={
                  <Text fontSize={12.5} fontWeight="600" color={text}>
                    {task.title}
                  </Text>
                }
                subTitle={
                  task.description ? (
                    <Text fontSize={11.5} fontWeight="400" color={subtle}>
                      {task.description}
                    </Text>
                  ) : null
                }
                iconAfter={
                  <XStack space="$1.5" alignItems="center">
                    <Pressable
                      onPress={() => {
                        if (!canAddTasks) {
                          toast.error(limitReachedMessage);
                          return;
                        }
                        quickAssign(task.id);
                      }}
                    >
                      <XStack alignItems="center" space="$1">
                        <Plus size={14} color={canAddTasks ? primary : muted} />
                        <Text fontSize={12} fontWeight="600" color={canAddTasks ? primary : muted}>
                          {assigningId === task.id ? t('common.processing', '...') : t('events.tasks.add', 'Add')}
                        </Text>
                      </XStack>
                    </Pressable>
                    <ChevronRight size={14} color={subtle} />
                  </XStack>
                }
                paddingVertical="$2"
                paddingHorizontal="$3"
              />
            </YGroup.Item>
          ))}
        </YGroup>
      )}
    </YStack>
  );

  const collectionsPanel = (
    <YStack space="$2">
      <Text fontSize="$xs" color={muted}>
        {t('events.tasks.importHint', 'Use predefined packs for your event type.')}
      </Text>
      {!canAddTasks ? (
        <Text fontSize={12} fontWeight="600" color={dangerText}>
          {limitReachedMessage}
          {limitReachedHint ? ` ${limitReachedHint}` : ''}
        </Text>
      ) : null}
      {collections.length > 6 ? (
        <Pressable onPress={() => setExpandedCollections((prev) => !prev)}>
          <Text fontSize={12} fontWeight="600" color={primary}>
            {expandedCollections ? t('events.tasks.hideCollections', 'Hide collections') : t('events.tasks.showCollections', 'Show all')}
          </Text>
        </Pressable>
      ) : null}
      {collections.length === 0 ? (
        <Text fontSize={13} fontWeight="500" color={muted}>
          {t('events.tasks.collectionsEmpty', 'No collections available.')}
        </Text>
      ) : (
        <YGroup {...({ borderWidth: 1, borderColor: border, borderRadius: "$4", overflow: "hidden" } as any)}>
          {(expandedCollections ? collections : collections.slice(0, 6)).map((collection) => (
            <YGroup.Item key={collection.id}>
              <ListItem
                hoverTheme
                pressTheme
                title={
                  <Text fontSize={12.5} fontWeight="600" color={text}>
                    {collection.name}
                  </Text>
                }
                subTitle={
                  collection.description ? (
                    <Text fontSize={11.5} fontWeight="400" color={subtle}>
                      {collection.description}
                    </Text>
                  ) : null
                }
                iconAfter={
                  <XStack space="$1.5" alignItems="center">
                    <Button
                      size="$2"
                      backgroundColor={withAlpha(primary, 0.12)}
                      borderWidth={1}
                      borderColor={withAlpha(primary, 0.35)}
                      onPress={() => {
                        if (!canAddTasks) {
                          toast.error(limitReachedMessage);
                          return;
                        }
                        importCollection(collection.id);
                      }}
                    >
                      <Text fontSize="$xs" fontWeight="700" color={canAddTasks ? primary : muted}>
                        {t('events.tasks.import', 'Import')}
                      </Text>
                    </Button>
                    <ChevronRight size={14} color={subtle} />
                  </XStack>
                }
                paddingVertical="$2"
                paddingHorizontal="$3"
              />
            </YGroup.Item>
          ))}
        </YGroup>
      )}
    </YStack>
  );

  const emotionsPanel = (
    <YStack space="$2">
      <XStack alignItems="center" justifyContent="space-between" flexWrap="wrap">
        <Text fontSize="$sm" fontWeight="700" color={text}>
          {t('events.tasks.tabs.emotions', 'Emotions')}
        </Text>
        <Button
          size="$2"
          backgroundColor={withAlpha(primary, 0.12)}
          borderWidth={1}
          borderColor={withAlpha(primary, 0.35)}
          onPress={() => {
            setEditingEmotion(null);
            setEmotionForm({ name: '', color: border });
            setShowEmotionSheet(true);
          }}
        >
          <Text fontSize="$xs" fontWeight="700" color={primary}>
            {t('events.tasks.addEmotion', 'Add emotion')}
          </Text>
        </Button>
      </XStack>
      {emotions.length === 0 ? (
        <Text fontSize={12} fontWeight="500" color={muted}>
          {t('events.tasks.emotionsEmpty', 'No emotions yet. Add one to help categorize tasks.')}
        </Text>
      ) : (
        <YGroup {...({ borderWidth: 1, borderColor: border, borderRadius: "$4", overflow: "hidden" } as any)}>
          {emotions.map((emotion) => (
            <YGroup.Item key={`emo-${emotion.id}`}>
              <ListItem
                hoverTheme
                pressTheme
                title={
                  <XStack alignItems="center" space="$2">
                    <Tag label={emotion.name ?? ''} color={emotion.color ?? border} />
                  </XStack>
                }
                iconAfter={
                  <XStack space="$2">
                    <Pressable
                      onPress={() => {
                        setEditingEmotion(emotion);
                        setEmotionForm({ name: emotion.name ?? '', color: emotion.color ?? border });
                        setShowEmotionSheet(true);
                      }}
                    >
                      <Pencil size={14} color={primary} />
                    </Pressable>
                    <Pressable onPress={() => removeEmotion(emotion.id)}>
                      <Trash2 size={14} color={danger} />
                    </Pressable>
                    <ChevronRight size={14} color={subtle} />
                  </XStack>
                }
                paddingVertical="$2"
                paddingHorizontal="$3"
              />
            </YGroup.Item>
          ))}
        </YGroup>
      )}
    </YStack>
  );

  return (
    <MobileShell
      activeTab="tasks"
      title={t('events.tasks.title', 'Photo tasks for guests')}
      onBack={back}
      headerActions={
        <XStack space="$2">
          <HeaderActionButton onPress={() => load()} ariaLabel={t('common.refresh', 'Refresh')}>
            <RefreshCcw size={18} color={text} />
          </HeaderActionButton>
        </XStack>
      }
    >
      {error ? (
        <MobileCard>
          <Text fontSize={13} fontWeight="600" color={danger}>
            {error}
          </Text>
          <CTAButton
            label={t('common.retry', 'Retry')}
            tone="ghost"
            fullWidth={false}
            onPress={() => load()}
          />
        </MobileCard>
      ) : null}

      {loading ? (
        <YStack space="$2">
          {Array.from({ length: 4 }).map((_, idx) => (
            <SkeletonCard key={`tsk-${idx}`} height={70} />
          ))}
        </YStack>
      ) : (
        <Card
          borderRadius={24}
          borderWidth={2}
          borderColor={border}
          backgroundColor={surface}
          padding="$3"
        >
          <YStack space="$3">
            <Card
              borderRadius={18}
              borderWidth={1}
              borderColor={border}
              backgroundColor={surfaceMuted}
              padding="$3"
            >
              <YStack space="$2">
                <XStack alignItems="center" justifyContent="space-between" space="$2">
                  <Text fontSize="$xs" fontWeight="700" color={text}>
                    {t('events.tasks.toggle.title', 'Photo tasks for guests')}
                  </Text>
                  <Pressable
                    onPress={() => setShowTaskDetails((prev) => !prev)}
                    aria-label={t(
                      'events.tasks.toggle.description',
                      'Control whether guests see mission cards and prompts.'
                    )}
                  >
                    <XStack
                      width={30}
                      height={30}
                      borderRadius={10}
                      alignItems="center"
                      justifyContent="center"
                      borderWidth={1}
                      borderColor={showTaskDetails ? withAlpha(primary, 0.45) : border}
                      backgroundColor={showTaskDetails ? withAlpha(primary, 0.12) : surface}
                    >
                      <Info size={14} color={showTaskDetails ? primary : muted} />
                    </XStack>
                  </Pressable>
                </XStack>
                <XStack
                  alignItems="center"
                  justifyContent="space-between"
                  paddingHorizontal="$2"
                  paddingVertical="$1.5"
                  borderRadius={12}
                  borderWidth={1}
                  borderColor={border}
                  backgroundColor={surface}
                >
                  <Text fontSize="$xs" fontWeight="700" color={text}>
                    {t('events.tasks.toggle.switchLabel', 'Photo task mode')}
                  </Text>
                  <XStack alignItems="center" space="$1.5">
                    <Switch
                      size="$3"
                      checked={tasksEnabled}
                      onCheckedChange={handleTasksToggle}
                      aria-label={t('events.tasks.toggle.switchLabel', 'Photo task mode')}
                      disabled={!canManageTasks || tasksToggleBusy}
                    >
                      <Switch.Thumb />
                    </Switch>
                    <PillBadge tone={tasksEnabled ? 'success' : 'warning'}>
                      {tasksEnabled
                        ? t('events.tasks.toggle.active', 'ACTIVE')
                        : t('events.tasks.toggle.inactive', 'INACTIVE')}
                    </PillBadge>
                  </XStack>
                </XStack>
                <Text fontSize="$xs" color={muted}>
                  {tasksEnabled
                    ? t('events.tasks.toggle.onLabel', 'Mission cards active')
                    : t('events.tasks.toggle.offLabel', 'Photo feed only')}
                </Text>
                {showTaskDetails ? (
                  <Text fontSize="$xs" color={muted}>
                    {t('events.tasks.toggle.description', 'Control whether guests see mission cards and prompts.')}
                  </Text>
                ) : null}
                {isMember && !canManageTasks ? (
                  <Text fontSize="$xs" color={muted}>
                    {t('events.tasks.toggle.permissionHint', 'You do not have permission to change photo tasks.')}
                  </Text>
                ) : null}
              </YStack>
            </Card>

            <Tabs
              value={activeTab}
              onValueChange={(value) => setActiveTab(value as TaskSectionKey)}
              flexDirection="column"
              alignItems="stretch"
              width="100%"
            >
              <XStack justifyContent="flex-end" marginBottom="$2">
                <ContextHelpLink slug="event-prep-checklist" />
              </XStack>
              <Tabs.List
                borderRadius={16}
                borderWidth={1}
                borderColor={border}
                backgroundColor={surfaceMuted}
                overflow="hidden"
                gap="$0"
              >
                {[
                  { value: 'assigned', label: t('events.tasks.tabs.tasks', 'Tasks') },
                  { value: 'library', label: t('events.tasks.tabs.library', 'Task Library') },
                  { value: 'emotions', label: t('events.tasks.tabs.emotions', 'Emotions') },
                  { value: 'collections', label: t('events.tasks.tabs.collections', 'Collections') },
                ].map((tab, index, arr) => {
                  const isActive = activeTab === tab.value;
                  return (
                    <Tabs.Tab
                      key={tab.value}
                      value={tab.value}
                      flex={1}
                      unstyled
                      paddingVertical="$2.5"
                      alignItems="center"
                      justifyContent="center"
                      backgroundColor={isActive ? primary : 'transparent'}
                      borderRightWidth={index === arr.length - 1 ? 0 : 1}
                      borderRightColor={border}
                      pressStyle={{ backgroundColor: isActive ? primary : surface }}
                    >
                      <Text fontSize="$sm" fontWeight={isActive ? '700' : '500'} color={isActive ? 'white' : text}>
                        {tab.label}
                      </Text>
                    </Tabs.Tab>
                  );
                })}
              </Tabs.List>

              <Tabs.Content value="assigned" paddingTop="$2">
                <Card borderRadius={18} borderWidth={1} borderColor={border} backgroundColor={surface} padding="$3">
                  <YStack space="$2">
                    <Card
                      borderRadius={16}
                      borderWidth={1}
                      borderColor={border}
                      backgroundColor={surfaceMuted}
                      padding="$2.5"
                    >
                      <XStack alignItems="center" space="$2">
                        <XStack flex={1}>
                          <MobileInput
                            type="search"
                            value={searchTerm}
                            onChange={(e) => setSearchTerm(e.target.value)}
                            placeholder={t('events.tasks.search', 'Search photo tasks')}
                            compact
                          />
                        </XStack>
                        <Pressable onPress={() => setShowEmotionFilterSheet(true)}>
                          <XStack
                            alignItems="center"
                            space="$1.5"
                            paddingVertical="$2"
                            paddingHorizontal="$3"
                            borderRadius={14}
                            borderWidth={1}
                            borderColor={border}
                            backgroundColor={surface}
                          >
                            <Text fontSize={11} fontWeight="700" color={text}>
                              {t('events.tasks.emotionFilterShort', 'Emotion')}
                            </Text>
                            <Text fontSize={11} color={muted}>
                              {emotionFilter
                                ? emotions.find((e) => String(e.id) === emotionFilter)?.name ?? t('events.tasks.customEmotion', 'Custom emotion')
                                : t('events.tasks.allEmotions', 'All')}
                            </Text>
                            <ChevronDown size={14} color={muted} />
                          </XStack>
                        </Pressable>
                      </XStack>
                    </Card>
                    {taskPanel}
                  </YStack>
                </Card>
              </Tabs.Content>

              <Tabs.Content value="library" paddingTop="$2">
                <Card borderRadius={18} borderWidth={1} borderColor={border} backgroundColor={surface} padding="$3">
                  {libraryPanel}
                </Card>
              </Tabs.Content>

              <Tabs.Content value="emotions" paddingTop="$2">
                <Card borderRadius={18} borderWidth={1} borderColor={border} backgroundColor={surface} padding="$3">
                  {emotionsPanel}
                </Card>
              </Tabs.Content>

              <Tabs.Content value="collections" paddingTop="$2">
                <Card borderRadius={18} borderWidth={1} borderColor={border} backgroundColor={surface} padding="$3">
                  {collectionsPanel}
                </Card>
              </Tabs.Content>
            </Tabs>
          </YStack>
        </Card>
      )}

      <MobileSheet
        open={showTaskSheet}
        onClose={() => setShowTaskSheet(false)}
        title={t('events.tasks.addTask', 'Fotoaufgabe hinzufügen')}
        footer={
          <CTAButton
            label={t('events.tasks.saveTask', 'Fotoaufgabe speichern')}
            onPress={() => createNewTask()}
            disabled={!canAddTasks}
          />
        }
      >
        <YStack space="$2">
          {!canAddTasks ? (
            <Text fontSize={12} fontWeight="600" color={dangerText}>
              {limitReachedMessage}
              {limitReachedHint ? ` ${limitReachedHint}` : ''}
            </Text>
          ) : null}
          <MobileField label={t('events.tasks.titleLabel', 'Titel')}>
            <MobileInput
              type="text"
              value={newTask.title}
              onChange={(e) => setNewTask((prev) => ({ ...prev, title: e.target.value }))}
              placeholder={t('events.tasks.titlePlaceholder', 'z.B. Erstes Gruppenfoto')}
            />
          </MobileField>
          <MobileField label={t('events.tasks.description', 'Beschreibung')}>
            <MobileTextArea
              value={newTask.description}
              onChange={(e) => setNewTask((prev) => ({ ...prev, description: e.target.value }))}
              placeholder={t('events.tasks.descriptionPlaceholder', 'Optionale Hinweise')}
              compact
              style={{ minHeight: 80 }}
            />
          </MobileField>
          <MobileField label={t('events.tasks.emotion', 'Emotion')}>
            <MobileSelect
              value={newTask.emotion_id}
              onChange={(e) => setNewTask((prev) => ({ ...prev, emotion_id: e.target.value }))}
            >
              <option value="">{t('events.tasks.emotionNone', 'Keine')}</option>
              {emotions.map((emotion) => (
                <option key={emotion.id} value={emotion.id}>
                  {emotion.name}
                </option>
              ))}
            </MobileSelect>
          </MobileField>
        </YStack>
      </MobileSheet>

      <MobileSheet
        open={showBulkSheet}
        onClose={() => setShowBulkSheet(false)}
        title={t('events.tasks.bulkAdd', 'Bulk add')}
        footer={
          <CTAButton
            label={t('events.tasks.saveTask', 'Fotoaufgabe speichern')}
            onPress={() => handleBulkAdd()}
            disabled={!canAddTasks}
          />
        }
      >
        <YStack space="$2">
          {!canAddTasks ? (
            <Text fontSize={12} fontWeight="600" color={dangerText}>
              {limitReachedMessage}
              {limitReachedHint ? ` ${limitReachedHint}` : ''}
            </Text>
          ) : null}
          {maxTasks !== null ? (
            <Text fontSize={11} color={muted}>
              {t('events.tasks.limitRemaining', {
                count: remainingTasks ?? 0,
                total: maxTasks,
                defaultValue: '{{count}} of {{total}} photo tasks remaining.',
              })}
            </Text>
          ) : null}
          <Text fontSize={12} color={muted}>
            {t('events.tasks.bulkHint', 'One photo task per line. These will be created and added to the event.')}
          </Text>
          <MobileTextArea
            value={bulkLines}
            onChange={(e) => setBulkLines(e.target.value)}
            placeholder={t('events.tasks.bulkPlaceholder', 'e.g.\nBride & groom portrait\nGroup photo main guests')}
            style={{ minHeight: 140, fontSize: 12.5 }}
          />
        </YStack>
      </MobileSheet>

      <MobileSheet
        open={showEmotionSheet}
        onClose={() => {
          setShowEmotionSheet(false);
          setEditingEmotion(null);
          setEmotionForm({ name: '', color: border });
        }}
        title={t('events.tasks.manageEmotions', 'Manage emotions')}
        footer={
          <CTAButton
            label={savingEmotion ? t('common.saving', 'Saving...') : t('events.tasks.saveEmotion', 'Emotion speichern')}
            onPress={() => saveEmotion()}
          />
        }
      >
        <YStack space="$2">
          <MobileField label={t('events.tasks.emotionName', 'Name')}>
            <MobileInput
              type="text"
              value={emotionForm.name}
              onChange={(e) => setEmotionForm((prev) => ({ ...prev, name: e.target.value }))}
              placeholder={t('events.tasks.emotionNamePlaceholder', 'z.B. Joy')}
            />
          </MobileField>
          <MobileField label={t('events.tasks.emotionColor', 'Farbe')}>
            <MobileInput
              type="color"
              value={emotionForm.color}
              onChange={(e) => setEmotionForm((prev) => ({ ...prev, color: e.target.value }))}
              style={{ padding: 0 }}
            />
          </MobileField>
        </YStack>
      </MobileSheet>

      <MobileSheet
        open={showEmotionFilterSheet}
        onClose={() => setShowEmotionFilterSheet(false)}
        title={t('events.tasks.emotionFilter', 'Emotion filter')}
        footer={
          <CTAButton label={t('common.close', 'Close')} onPress={() => setShowEmotionFilterSheet(false)} />
        }
      >
        <RadioGroup
          value={emotionFilter}
          onValueChange={(val) => {
            setEmotionFilter(val);
            setShowEmotionFilterSheet(false);
          }}
        >
          <YStack space="$2">
            <XStack alignItems="center" space="$2">
              <RadioGroup.Item value="">
                <RadioGroup.Indicator />
              </RadioGroup.Item>
              <Text fontSize={12.5} color={text}>
                {t('events.tasks.allEmotions', 'All')}
              </Text>
            </XStack>
            {emotions.map((emotion) => (
              <XStack key={`emo-filter-${emotion.id}`} alignItems="center" space="$2">
                <RadioGroup.Item value={String(emotion.id)}>
                  <RadioGroup.Indicator />
                </RadioGroup.Item>
                <Text fontSize={12.5} color={emotion.color ?? text}>
                  {emotion.name ?? ''}
                </Text>
              </XStack>
            ))}
          </YStack>
        </RadioGroup>
      </MobileSheet>

      <AlertDialog
        open={Boolean(deleteCandidate)}
        onOpenChange={(open) => {
          if (!open) {
            setDeleteCandidate(null);
          }
        }}
      >
        <AlertDialog.Portal>
          <AlertDialog.Overlay backgroundColor={`${overlay}66` as any} />
          <AlertDialog.Content
            {...({ borderRadius: 20 } as any)}
            borderWidth={1}
            borderColor={border}
            backgroundColor={surface}
            padding="$4"
            maxWidth={420}
            width="90%"
          >
            <YStack space="$3">
              <AlertDialog.Title>
                <Text fontSize="$md" fontWeight="800" color={text}>
                  {t('events.tasks.removeTitle', 'Remove photo task?')}
                </Text>
              </AlertDialog.Title>
              <AlertDialog.Description>
                <Text fontSize="$sm" color={muted}>
                  {deleteCandidate
                    ? t('events.tasks.removeBody', 'This will remove "{{title}}" from the event.', { title: deleteCandidate.title })
                    : t('events.tasks.removeBodyFallback', 'This will remove the photo task from the event.')}
                </Text>
              </AlertDialog.Description>
              <XStack space="$2" justifyContent="flex-end">
                <AlertDialog.Cancel asChild>
                  <CTAButton
                    label={t('common.cancel', 'Cancel')}
                    tone="ghost"
                    fullWidth={false}
                    onPress={() => setDeleteCandidate(null)}
                  />
                </AlertDialog.Cancel>
                <AlertDialog.Action asChild>
                  <CTAButton
                    label={t('events.tasks.remove', 'Remove')}
                    tone="danger"
                    fullWidth={false}
                    onPress={() => confirmDeleteTask()}
                  />
                </AlertDialog.Action>
              </XStack>
            </YStack>
          </AlertDialog.Content>
        </AlertDialog.Portal>
      </AlertDialog>

      <AlertDialog
        open={bulkDeleteOpen}
        onOpenChange={(open) => {
          if (!open) {
            setBulkDeleteOpen(false);
          }
        }}
      >
        <AlertDialog.Portal>
          <AlertDialog.Overlay backgroundColor={`${overlay}66` as any} />
          <AlertDialog.Content
            {...({ borderRadius: 20 } as any)}
            borderWidth={1}
            borderColor={border}
            backgroundColor={surface}
            padding="$4"
            maxWidth={420}
            width="90%"
          >
            <YStack space="$3">
              <AlertDialog.Title>
                <Text fontSize="$md" fontWeight="800" color={text}>
                  {t('events.tasks.bulkRemoveTitle', 'Auswahl löschen')}
                </Text>
              </AlertDialog.Title>
              <AlertDialog.Description>
                <Text fontSize="$sm" color={muted}>
                  {t('events.tasks.bulkRemoveBody', 'This will remove the selected photo tasks from the event.')}
                </Text>
              </AlertDialog.Description>
              <XStack space="$2" justifyContent="flex-end">
                <AlertDialog.Cancel asChild>
                  <CTAButton
                    label={t('common.cancel', 'Cancel')}
                    tone="ghost"
                    fullWidth={false}
                    onPress={() => setBulkDeleteOpen(false)}
                  />
                </AlertDialog.Cancel>
                <AlertDialog.Action asChild>
                  <CTAButton
                    label={t('events.tasks.remove', 'Remove')}
                    tone="danger"
                    fullWidth={false}
                    onPress={() => confirmBulkDelete()}
                    disabled={bulkDeleteBusy}
                  />
                </AlertDialog.Action>
              </XStack>
            </YStack>
          </AlertDialog.Content>
        </AlertDialog.Portal>
      </AlertDialog>

      {canAddTasks ? (
        <FloatingActionButton
          onPress={() => {
            if (!canAddTasks) {
              toast.error(limitReachedMessage);
              return;
            }
            setShowFabMenu(true);
          }}
          label={t('events.tasks.add', 'Add')}
          icon={Plus}
        />
      ) : null}

      <MobileSheet
        open={showFabMenu}
        onClose={() => setShowFabMenu(false)}
        title={t('events.tasks.actions', 'Aktionen')}
        footer={null}
      >
        <YGroup {...({ borderWidth: 1, borderColor: border, borderRadius: "$4", overflow: "hidden" } as any)}>
          <YGroup.Item>
            <ListItem
              hoverTheme
              pressTheme
              title={
                <Text fontSize={12.5} fontWeight="600" color={text}>
                  {t('events.tasks.addTask', 'Fotoaufgabe hinzufügen')}
                </Text>
              }
              onPress={() => {
                if (!canAddTasks) {
                  toast.error(limitReachedMessage);
                  return;
                }
                setShowFabMenu(false);
                setShowTaskSheet(true);
              }}
              paddingVertical="$2"
              paddingHorizontal="$3"
              iconAfter={<ChevronRight size={14} color={subtle} />}
            />
          </YGroup.Item>
          <YGroup.Item>
            <ListItem
              hoverTheme
              pressTheme
              title={
                <Text fontSize={12.5} fontWeight="600" color={text}>
                  {t('events.tasks.bulkAdd', 'Bulk add')}
                </Text>
              }
              onPress={() => {
                if (!canAddTasks) {
                  toast.error(limitReachedMessage);
                  return;
                }
                setShowFabMenu(false);
                setShowBulkSheet(true);
              }}
              paddingVertical="$2"
              paddingHorizontal="$3"
              iconAfter={<ChevronRight size={14} color={subtle} />}
            />
          </YGroup.Item>
          <YGroup.Item>
            <ListItem
              hoverTheme
              pressTheme
              title={
                <Text fontSize={12.5} fontWeight="600" color={text}>
                  {t('events.tasks.manageEmotions', 'Manage emotions')}
                </Text>
              }
              subTitle={
                <Text fontSize={11.5} fontWeight="400" color={subtle}>
                  {t('events.tasks.manageEmotionsHint', 'Filter and keep your taxonomy tidy.')}
                </Text>
              }
              onPress={() => {
                setShowFabMenu(false);
                setActiveTab('emotions');
              }}
              paddingVertical="$2"
              paddingHorizontal="$3"
              iconAfter={<ChevronRight size={14} color={subtle} />}
            />
          </YGroup.Item>
        </YGroup>
      </MobileSheet>
    </MobileShell>
  );
}
