import { useCallback, useEffect, useLayoutEffect, useState } from 'react';
import {
  ActivityIndicator,
  Alert,
  FlatList,
  Image,
  InteractionManager,
  KeyboardAvoidingView,
  Modal,
  Pressable,
  Platform,
  ScrollView,
  StyleSheet,
  TextInput,
  View,
} from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import { ResizeMode, Video } from 'expo-av';
import { useLocalSearchParams, useRouter } from 'expo-router';
import { useFocusEffect, useNavigation } from '@react-navigation/native';

import { ThemedText } from '@/components/themed-text';
import { ThemedView } from '@/components/themed-view';
import { IconSymbol } from '@/components/ui/icon-symbol';
import { ThemedButton } from '@/components/themed-button';
import { IconButton } from '@/components/icon-button';
import { Colors, Fonts } from '@/constants/theme';
import { useTranslation } from '@/localization/i18n';
import { dbPromise, initCoreTables } from '@/services/db';
import { useColorScheme } from '@/hooks/use-color-scheme';
import { ZoomImageModal } from '@/components/zoom-image-modal';

type FieldRow = {
  id: number;
  name: string | null;
  area_ha: number | null;
  notes: string | null;
  photo_uri: string | null;
  created_at: string | null;
  updated_at: string | null;
};

type FieldMediaRow = {
  uri: string | null;
};

export default function FieldsScreen() {
  const { t } = useTranslation();
  const router = useRouter();
  const navigation = useNavigation();
  const { from } = useLocalSearchParams<{ from?: string }>();
  const theme = useColorScheme() ?? 'light';
  const palette = Colors[theme];

  useLayoutEffect(() => {
    if (from === 'home') {
      navigation.setOptions({
        headerLeft: () => (
          <Pressable onPress={() => router.replace('/')} hitSlop={10} style={{ paddingHorizontal: 8 }}>
            <IconSymbol size={20} name="chevron.left" color={palette.text} />
          </Pressable>
        ),
      });
    }
  }, [from, navigation, palette.text, router]);
  const pageSize = 12;
  const [fields, setFields] = useState<FieldRow[]>([]);
  const [status, setStatus] = useState(t('fields.loading'));
  const [name, setName] = useState('');
  const [areaHa, setAreaHa] = useState('');
  const [notes, setNotes] = useState('');
  const [photoUri, setPhotoUri] = useState<string | null>(null);
  const [mediaUris, setMediaUris] = useState<string[]>([]);
  const [newModalVisible, setNewModalVisible] = useState(false);
  const [editingId, setEditingId] = useState<number | null>(null);
  const [editModalVisible, setEditModalVisible] = useState(false);
  const [editName, setEditName] = useState('');
  const [editAreaHa, setEditAreaHa] = useState('');
  const [editNotes, setEditNotes] = useState('');
  const [editPhotoUri, setEditPhotoUri] = useState<string | null>(null);
  const [editMediaUris, setEditMediaUris] = useState<string[]>([]);
  const [zoomUri, setZoomUri] = useState<string | null>(null);
  const [pendingZoomUri, setPendingZoomUri] = useState<string | null>(null);
  const [sheetZoomUri, setSheetZoomUri] = useState<string | null>(null);

  function closeSheetViewer() {
    setSheetZoomUri(null);
    setEditModalVisible(false);
    setNewModalVisible(false);
    setEditingId(null);
    setEditErrors({});
    setNewErrors({});
  }
  const [newErrors, setNewErrors] = useState<{ name?: string; area?: string }>({});
  const [editErrors, setEditErrors] = useState<{ name?: string; area?: string }>({});
  const [page, setPage] = useState(1);
  const [hasMore, setHasMore] = useState(true);
  const [loadingMore, setLoadingMore] = useState(false);

  useEffect(() => {
    let isActive = true;

    async function loadFields() {
      await fetchFieldsPage(1, true, isActive);
    }

    loadFields();
    return () => {
      isActive = false;
    };
  }, [t]);

  useFocusEffect(
    useCallback(() => {
      fetchFieldsPage(1, true);
    }, [])
  );

  useEffect(() => {
    if (!editModalVisible && !newModalVisible && pendingZoomUri) {
      const uri = pendingZoomUri;
      setPendingZoomUri(null);
      InteractionManager.runAfterInteractions(() => {
        setTimeout(() => setZoomUri(uri), 150);
      });
    }
  }, [editModalVisible, newModalVisible, pendingZoomUri]);

  async function fetchFieldsPage(pageToLoad: number, replace: boolean, isActive = true) {
    try {
      await initCoreTables();
      const db = await dbPromise;
      const rows = await db.getAllAsync<FieldRow>(
        'SELECT id, name, area_ha, notes, photo_uri, created_at, updated_at FROM fields ORDER BY id DESC LIMIT ? OFFSET ?;',
        pageSize,
        (pageToLoad - 1) * pageSize
      );
      if (!isActive) return;
      setFields((prev) => (replace ? rows : [...prev, ...rows]));
      setHasMore(rows.length === pageSize);
      setPage(pageToLoad);
      if (replace) {
        setStatus(rows.length === 0 ? t('fields.empty') : '');
      }
    } catch (error) {
      if (isActive) setStatus(`Error: ${String(error)}`);
    } finally {
      if (isActive) setLoadingMore(false);
    }
  }

  async function handleLoadMore() {
    if (loadingMore || !hasMore) return;
    setLoadingMore(true);
    const nextPage = page + 1;
    await fetchFieldsPage(nextPage, false);
  }

  async function handleSave() {
    const trimmedName = name.trim();
    const area = areaHa.trim() ? Number(areaHa) : null;
    const nextErrors: { name?: string; area?: string } = {};
    if (!trimmedName) {
      nextErrors.name = t('fields.nameRequired');
    }
    if (areaHa.trim() && !Number.isFinite(area)) {
      nextErrors.area = t('fields.areaInvalid');
    }
    setNewErrors(nextErrors);
    if (Object.keys(nextErrors).length > 0) {
      setStatus(nextErrors.name ?? nextErrors.area ?? t('fields.nameRequired'));
      return false;
    }
    try {
      const db = await dbPromise;
      const now = new Date().toISOString();
      const primaryUri = mediaUris[0] ?? normalizeMediaUri(photoUri);
      const result = await db.runAsync(
        'INSERT INTO fields (name, area_ha, notes, photo_uri, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?);',
        trimmedName,
        area,
        notes.trim() || null,
        primaryUri ?? null,
        now,
        now
      );
      const fieldId = Number(result.lastInsertRowId);
      if (fieldId) {
        const mediaToInsert = uniqueMediaUris([
          ...mediaUris,
          ...(normalizeMediaUri(photoUri) ? [normalizeMediaUri(photoUri) as string] : []),
        ]);
        for (const uri of mediaToInsert) {
          await db.runAsync(
            'INSERT INTO field_media (field_id, uri, media_type, created_at) VALUES (?, ?, ?, ?);',
            fieldId,
            uri,
            isVideoUri(uri) ? 'video' : 'image',
            now
          );
        }
      }
      setName('');
      setAreaHa('');
      setNotes('');
      setPhotoUri(null);
      setMediaUris([]);
      setNewErrors({});
      await fetchFieldsPage(1, true);
      setStatus(t('fields.saved'));
      return true;
    } catch (error) {
      setStatus(`Error: ${String(error)}`);
      return false;
    }
  }

  async function handleDelete(id: number) {
    try {
      const db = await dbPromise;
      await db.runAsync('DELETE FROM field_media WHERE field_id = ?;', id);
      await db.runAsync('DELETE FROM fields WHERE id = ?;', id);
      await fetchFieldsPage(1, true);
    } catch (error) {
      setStatus(`Error: ${String(error)}`);
    }
  }

  function confirmDelete(id: number) {
    Alert.alert(
      t('fields.deleteTitle'),
      t('fields.deleteMessage'),
      [
        { text: t('fields.cancel'), style: 'cancel' },
        { text: t('fields.delete'), style: 'destructive', onPress: () => handleDelete(id) },
      ]
    );
  }

  async function startEdit(field: FieldRow) {
    router.push(`/logbook/fields/${field.id}`);
  }

  function cancelEdit() {
    setEditingId(null);
    setEditName('');
    setEditAreaHa('');
    setEditNotes('');
    setEditPhotoUri(null);
    setEditMediaUris([]);
    setEditErrors({});
    setSheetZoomUri(null);
    setEditModalVisible(false);
    setStatus('');
  }

  async function handleUpdate() {
    if (!editingId) return;
    const trimmedName = editName.trim();
    const area = editAreaHa.trim() ? Number(editAreaHa) : null;
    const nextErrors: { name?: string; area?: string } = {};
    if (!trimmedName) {
      nextErrors.name = t('fields.nameRequired');
    }
    if (editAreaHa.trim() && !Number.isFinite(area)) {
      nextErrors.area = t('fields.areaInvalid');
    }
    setEditErrors(nextErrors);
    if (Object.keys(nextErrors).length > 0) {
      setStatus(nextErrors.name ?? nextErrors.area ?? t('fields.nameRequired'));
      return;
    }
    try {
      const db = await dbPromise;
      const now = new Date().toISOString();
      const primaryUri = editMediaUris[0] ?? normalizeMediaUri(editPhotoUri);
      await db.runAsync(
        'UPDATE fields SET name = ?, area_ha = ?, notes = ?, photo_uri = ?, updated_at = ? WHERE id = ?;',
        trimmedName,
        area,
        editNotes.trim() || null,
        primaryUri ?? null,
        now,
        editingId
      );
      await db.runAsync('DELETE FROM field_media WHERE field_id = ?;', editingId);
      const mediaToInsert = uniqueMediaUris([
        ...editMediaUris,
        ...(normalizeMediaUri(editPhotoUri) ? [normalizeMediaUri(editPhotoUri) as string] : []),
      ]);
      for (const uri of mediaToInsert) {
        await db.runAsync(
          'INSERT INTO field_media (field_id, uri, media_type, created_at) VALUES (?, ?, ?, ?);',
          editingId,
          uri,
          isVideoUri(uri) ? 'video' : 'image',
          now
        );
      }
      setEditModalVisible(false);
      setEditingId(null);
      setEditErrors({});
      await fetchFieldsPage(1, true);
      setStatus(t('fields.saved'));
    } catch (error) {
      setStatus(`Error: ${String(error)}`);
    }
  }

  const inputStyle = [
    styles.input,
    {
      borderColor: palette.border,
      backgroundColor: palette.input,
      color: palette.text,
    },
  ];

  return (
    <>
    <FlatList
      data={fields}
      keyExtractor={(item) => String(item.id)}
      extraData={[photoUri, editModalVisible, editPhotoUri, name, areaHa, notes, status]}
      onEndReached={handleLoadMore}
      onEndReachedThreshold={0.4}
      renderItem={({ item }) => {
        const mediaUri = normalizeMediaUri(item.photo_uri);
        return (
          <Pressable onPress={() => startEdit(item)}>
          <ThemedView style={[styles.card, { backgroundColor: palette.card, borderColor: palette.border }]}>
            <ThemedText type="subtitle">{item.name || t('fields.unnamed')}</ThemedText>
            {item.area_ha !== null ? (
              <ThemedText style={styles.meta}>
                {t('fields.areaLabel')} {item.area_ha}
              </ThemedText>
            ) : null}
            {mediaUri ? (
              isVideoUri(mediaUri) ? (
                <Video
                  source={{ uri: mediaUri }}
                  style={styles.videoPreview}
                  useNativeControls
                  resizeMode={ResizeMode.CONTAIN}
                  isMuted
                />
              ) : (
                <Pressable onPress={() => setZoomUri(mediaUri)}>
                  <Image
                    source={{ uri: mediaUri }}
                    style={styles.photoPreview}
                    resizeMode="contain"
                    onError={(error) =>
                      console.log('[Fields] List image error:', mediaUri, error.nativeEvent)
                    }
                    onLoad={() => console.log('[Fields] List image loaded:', mediaUri)}
                  />
                </Pressable>
              )
            ) : null}
            {item.notes ? <ThemedText>{item.notes}</ThemedText> : null}
            <View style={styles.buttonRow}>
              <IconButton
                name="trash"
                onPress={() => confirmDelete(item.id)}
                accessibilityLabel={t('fields.delete')}
                variant="danger"
              />
              {item.updated_at ? (
                  <ThemedText style={styles.metaEnd}>{formatDate(item.updated_at)}</ThemedText>
                ) : null}
              </View>
            </ThemedView>
          </Pressable>
        );
      }}
        ItemSeparatorComponent={() => <View style={styles.separator} />}
        ListHeaderComponent={
          <View>
            <ThemedView style={styles.hero}>
              <Image source={require('@/assets/images/fields.jpg')} style={styles.heroImage} />
            </ThemedView>
            <ThemedView style={styles.titleContainer}>
              <ThemedText type="title" style={{ fontFamily: Fonts.rounded }}>
                {t('fields.title')}
              </ThemedText>
            </ThemedView>

            {status ? (
              <ThemedView style={styles.section}>
                <ThemedText>{status}</ThemedText>
              </ThemedView>
            ) : null}

            <ThemedView style={styles.section}>
              <Pressable
                style={styles.newButton}
                onPress={() => {
                  setNewErrors({});
                  setNewModalVisible(true);
                }}>
                <IconSymbol size={18} name="plus.circle.fill" color="#2F7D4F" />
                <ThemedText style={styles.newButtonText}>{t('fields.new')}</ThemedText>
              </Pressable>
            </ThemedView>
          </View>
        }
        ListFooterComponent={
          <View style={styles.footer}>
            {loadingMore ? <ActivityIndicator /> : null}
          </View>
        }
      />
      <Modal
        visible={editModalVisible}
        animationType="slide"
        transparent
        onRequestClose={cancelEdit}>
        <View style={styles.sheetOverlay}>
          <Pressable
            style={styles.sheetBackdrop}
            pointerEvents={sheetZoomUri ? 'none' : 'auto'}
            onPress={() => {
              if (sheetZoomUri) {
                setSheetZoomUri(null);
                return;
              }
              cancelEdit();
            }}
          />
          <KeyboardAvoidingView
            behavior={Platform.OS === 'ios' ? 'padding' : undefined}
            keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 0}
            style={styles.keyboardAvoid}
            pointerEvents={sheetZoomUri ? 'none' : 'auto'}>
            <Pressable
              style={[
                styles.sheet,
                { backgroundColor: palette.card, borderColor: palette.border, paddingBottom: 0 },
              ]}
              onPress={(event) => {
                event.stopPropagation();
              }}
              onStartShouldSetResponder={() => true}
              pointerEvents={sheetZoomUri ? 'none' : 'auto'}>
              <ScrollView
                keyboardShouldPersistTaps="handled"
                contentContainerStyle={styles.sheetContent}>
                <ThemedText type="subtitle">{t('fields.edit')}</ThemedText>
            <ThemedText>
              {t('fields.name')}
              <ThemedText style={styles.requiredMark}> *</ThemedText>
            </ThemedText>
            <TextInput
              value={editName}
              onChangeText={(value) => {
                setEditName(value);
                if (editErrors.name) {
                  setEditErrors((prev) => ({ ...prev, name: undefined }));
                }
              }}
              placeholder={t('fields.name')}
              placeholderTextColor={palette.placeholder}
              style={inputStyle}
            />
            {editErrors.name ? <ThemedText style={styles.errorText}>{editErrors.name}</ThemedText> : null}
            <ThemedText>{t('fields.area')}</ThemedText>
            <TextInput
              value={editAreaHa}
              onChangeText={(value) => {
                setEditAreaHa(value);
                if (editErrors.area) {
                  setEditErrors((prev) => ({ ...prev, area: undefined }));
                }
              }}
              placeholder={t('fields.areaPlaceholder')}
              placeholderTextColor={palette.placeholder}
              style={inputStyle}
              keyboardType="decimal-pad"
            />
            {editErrors.area ? <ThemedText style={styles.errorText}>{editErrors.area}</ThemedText> : null}
            <ThemedText>{t('fields.notes')}</ThemedText>
          <TextInput
            value={editNotes}
            onChangeText={setEditNotes}
            placeholder={t('fields.notesPlaceholder')}
            placeholderTextColor={palette.placeholder}
            style={inputStyle}
            multiline
          />
          <ThemedText>{t('fields.addMedia')}</ThemedText>
          {editMediaUris.length > 0 ? (
            isVideoUri(normalizeMediaUri(editPhotoUri) as string) ? (
              <Pressable
                onPress={(event) => {
                  event.stopPropagation();
                  setSheetZoomUri(normalizeMediaUri(editPhotoUri) as string);
                }}>
                <Video
                  source={{ uri: normalizeMediaUri(editPhotoUri) as string }}
                  style={styles.videoPreview}
                  useNativeControls
                  resizeMode={ResizeMode.CONTAIN}
                  isMuted
                />
              </Pressable>
            ) : (
              <Pressable
                onPress={(event) => {
                  event.stopPropagation();
                  setSheetZoomUri(normalizeMediaUri(editPhotoUri) as string);
                }}>
                <Image
                  key={normalizeMediaUri(editPhotoUri) as string}
                  source={{ uri: normalizeMediaUri(editPhotoUri) as string }}
                  style={styles.photoPreview}
                  resizeMode="contain"
                  onError={(error) =>
                    console.log(
                      '[Fields] Edit image error:',
                      normalizeMediaUri(editPhotoUri) as string,
                      error.nativeEvent
                    )
                  }
                  onLoad={() =>
                    console.log(
                      '[Fields] Edit image loaded:',
                      normalizeMediaUri(editPhotoUri) as string
                    )
                  }
                />
              </Pressable>
            )
          ) : (
            <ThemedText style={styles.photoPlaceholder}>{t('fields.noPhoto')}</ThemedText>
          )}
          {editMediaUris.length > 0 ? (
            <ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.mediaStrip}>
              {editMediaUris.map((uri) => (
                <Pressable
                  key={uri}
                  style={styles.mediaChip}
                  onPress={(event) => {
                    event.stopPropagation();
                    setSheetZoomUri(uri);
                  }}>
                  {isVideoUri(uri) ? (
                    <View style={styles.videoThumb}>
                      <ThemedText style={styles.videoThumbText}>▶</ThemedText>
                    </View>
                  ) : (
                    <Image source={{ uri }} style={styles.mediaThumb} resizeMode="cover" />
                  )}
                  <Pressable
                    style={styles.removeBadge}
                    onPress={(event) => {
                      event.stopPropagation();
                      setEditMediaUris((prev) => {
                        const next = prev.filter((item) => item !== uri);
                        setEditPhotoUri((current) => (current === uri ? next[0] ?? null : current));
                        return next;
                      });
                    }}>
                    <ThemedText style={styles.removeBadgeText}>×</ThemedText>
                  </Pressable>
                </Pressable>
              ))}
            </ScrollView>
          ) : null}
          <View style={styles.photoRow}>
            <ThemedButton
              title={t('fields.pickFromGallery')}
              onPress={() =>
                handlePickPhoto(
                  (uri) => {
                    if (!uri) return;
                    setEditPhotoUri((prev) => prev ?? uri);
                  },
                  (uris) => {
                    if (uris.length === 0) return;
                    setEditMediaUris((prev) => uniqueMediaUris([...prev, ...uris]));
                    setEditPhotoUri((prev) => prev ?? uris[0]);
                  }
                )
              }
              variant="secondary"
            />
            <ThemedButton
              title={t('fields.takeMedia')}
              onPress={() =>
                handleTakePhoto(
                  (uri) => {
                    if (!uri) return;
                    setEditPhotoUri((prev) => prev ?? uri);
                    setEditMediaUris((prev) => uniqueMediaUris([...prev, uri]));
                  },
                  (code) =>
                    setStatus(
                      code === 'cameraDenied'
                        ? t('tasks.cameraDenied')
                        : t('tasks.cameraError')
                    )
                )
              }
              variant="secondary"
            />
          </View>
          <View style={styles.modalActions}>
            <ThemedButton title={t('fields.cancel')} onPress={cancelEdit} variant="secondary" />
            <ThemedButton title={t('fields.update')} onPress={handleUpdate} />
          </View>
              </ScrollView>
            </Pressable>
          </KeyboardAvoidingView>
          {sheetZoomUri ? (
            <View style={styles.sheetZoomOverlay} pointerEvents="box-none">
              <Pressable
                style={styles.sheetZoomBackdrop}
                onPress={() => setSheetZoomUri(null)}
              />
              <Pressable
                style={styles.sheetZoomClose}
                onPress={closeSheetViewer}
                hitSlop={12}
                pointerEvents="auto">
                <ThemedText style={styles.sheetZoomCloseText}>{t('common.close')}</ThemedText>
              </Pressable>
              <View style={styles.sheetZoomContent} pointerEvents="auto">
                {isVideoUri(sheetZoomUri) ? (
                  <Video
                    source={{ uri: sheetZoomUri }}
                    style={styles.sheetZoomVideo}
                    useNativeControls
                    resizeMode={ResizeMode.CONTAIN}
                  />
                ) : (
                  <ScrollView
                    style={styles.sheetZoomScroll}
                    contentContainerStyle={styles.sheetZoomScrollContent}
                    minimumZoomScale={1}
                    maximumZoomScale={3}
                    centerContent
                    showsHorizontalScrollIndicator={false}
                    showsVerticalScrollIndicator={false}>
                    <Image source={{ uri: sheetZoomUri }} style={styles.sheetZoomImage} resizeMode="contain" />
                  </ScrollView>
                )}
              </View>
            </View>
          ) : null}
        </View>
      </Modal>
      <Modal
        visible={newModalVisible}
        animationType="slide"
        transparent
        onRequestClose={() => setNewModalVisible(false)}>
        <View style={styles.sheetOverlay}>
          <Pressable
            style={styles.sheetBackdrop}
            pointerEvents={sheetZoomUri ? 'none' : 'auto'}
            onPress={() => {
              if (sheetZoomUri) {
                setSheetZoomUri(null);
                return;
              }
              setNewModalVisible(false);
            }}
          />
          <KeyboardAvoidingView
            behavior={Platform.OS === 'ios' ? 'padding' : undefined}
            keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 0}
            style={styles.keyboardAvoid}
            pointerEvents={sheetZoomUri ? 'none' : 'auto'}>
            <Pressable
              style={[
                styles.sheet,
                { backgroundColor: palette.card, borderColor: palette.border, paddingBottom: 0 },
              ]}
              onPress={(event) => {
                event.stopPropagation();
              }}
              onStartShouldSetResponder={() => true}
              pointerEvents={sheetZoomUri ? 'none' : 'auto'}>
              <ScrollView
                keyboardShouldPersistTaps="handled"
                contentContainerStyle={styles.sheetContent}>
                <ThemedText type="subtitle">{t('fields.new')}</ThemedText>
            <ThemedText>
              {t('fields.name')}
              <ThemedText style={styles.requiredMark}> *</ThemedText>
            </ThemedText>
            <TextInput
              value={name}
              onChangeText={(value) => {
                setName(value);
                if (newErrors.name) {
                  setNewErrors((prev) => ({ ...prev, name: undefined }));
                }
              }}
              placeholder={t('fields.name')}
              placeholderTextColor={palette.placeholder}
              style={inputStyle}
            />
            {newErrors.name ? <ThemedText style={styles.errorText}>{newErrors.name}</ThemedText> : null}
            <ThemedText>{t('fields.area')}</ThemedText>
            <TextInput
              value={areaHa}
              onChangeText={(value) => {
                setAreaHa(value);
                if (newErrors.area) {
                  setNewErrors((prev) => ({ ...prev, area: undefined }));
                }
              }}
              placeholder={t('fields.areaPlaceholder')}
              placeholderTextColor={palette.placeholder}
              style={inputStyle}
              keyboardType="decimal-pad"
            />
            {newErrors.area ? <ThemedText style={styles.errorText}>{newErrors.area}</ThemedText> : null}
            <ThemedText>{t('fields.notes')}</ThemedText>
            <TextInput
              value={notes}
              onChangeText={setNotes}
              placeholder={t('fields.notesPlaceholder')}
              placeholderTextColor={palette.placeholder}
              style={inputStyle}
              multiline
            />
            <ThemedText>{t('fields.addMedia')}</ThemedText>
            {mediaUris.length > 0 ? (
              isVideoUri(normalizeMediaUri(photoUri) as string) ? (
                <Pressable
                  onPress={(event) => {
                    event.stopPropagation();
                    setSheetZoomUri(normalizeMediaUri(photoUri) as string);
                  }}>
                  <Video
                    source={{ uri: normalizeMediaUri(photoUri) as string }}
                    style={styles.videoPreview}
                    useNativeControls
                    resizeMode={ResizeMode.CONTAIN}
                    isMuted
                  />
                </Pressable>
              ) : (
                <Pressable
                  onPress={(event) => {
                    event.stopPropagation();
                    setSheetZoomUri(normalizeMediaUri(photoUri) as string);
                  }}>
                  <Image
                    key={normalizeMediaUri(photoUri) as string}
                    source={{ uri: normalizeMediaUri(photoUri) as string }}
                    style={styles.photoPreview}
                    resizeMode="contain"
                    onError={(error) =>
                      console.log(
                        '[Fields] New image error:',
                        normalizeMediaUri(photoUri) as string,
                        error.nativeEvent
                      )
                    }
                    onLoad={() =>
                      console.log(
                        '[Fields] New image loaded:',
                        normalizeMediaUri(photoUri) as string
                      )
                    }
                  />
                </Pressable>
              )
            ) : (
              <ThemedText style={styles.photoPlaceholder}>{t('fields.noPhoto')}</ThemedText>
            )}
            {mediaUris.length > 0 ? (
              <ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.mediaStrip}>
                {mediaUris.map((uri) => (
                  <Pressable
                    key={uri}
                    style={styles.mediaChip}
                  onPress={(event) => {
                    event.stopPropagation();
                    setSheetZoomUri(uri);
                  }}>
                    {isVideoUri(uri) ? (
                      <View style={styles.videoThumb}>
                        <ThemedText style={styles.videoThumbText}>▶</ThemedText>
                      </View>
                    ) : (
                      <Image source={{ uri }} style={styles.mediaThumb} resizeMode="cover" />
                    )}
                    <Pressable
                      style={styles.removeBadge}
                      onPress={(event) => {
                        event.stopPropagation();
                        setMediaUris((prev) => {
                          const next = prev.filter((item) => item !== uri);
                          setPhotoUri((current) => (current === uri ? next[0] ?? null : current));
                          return next;
                        });
                      }}>
                      <ThemedText style={styles.removeBadgeText}>×</ThemedText>
                    </Pressable>
                  </Pressable>
                ))}
              </ScrollView>
            ) : null}
            <View style={styles.photoRow}>
              <ThemedButton
                title={t('fields.pickFromGallery')}
                onPress={() =>
                  handlePickPhoto(
                    (uri) => {
                      if (!uri) return;
                      setPhotoUri((prev) => prev ?? uri);
                    },
                    (uris) => {
                      if (uris.length === 0) return;
                      setMediaUris((prev) => uniqueMediaUris([...prev, ...uris]));
                      setPhotoUri((prev) => prev ?? uris[0]);
                    }
                  )
                }
                variant="secondary"
              />
              <ThemedButton
                title={t('fields.takeMedia')}
                onPress={() =>
                  handleTakePhoto(
                    (uri) => {
                      if (!uri) return;
                      setPhotoUri((prev) => prev ?? uri);
                      setMediaUris((prev) => uniqueMediaUris([...prev, uri]));
                    },
                    (code) =>
                      setStatus(
                        code === 'cameraDenied'
                          ? t('tasks.cameraDenied')
                          : t('tasks.cameraError')
                      )
                  )
                }
                variant="secondary"
              />
            </View>
            <View style={styles.modalActions}>
              <ThemedButton
                title={t('fields.cancel')}
                onPress={() => setNewModalVisible(false)}
                variant="secondary"
              />
              <ThemedButton
                title={t('fields.save')}
                onPress={async () => {
                  const ok = await handleSave();
                  if (ok) setNewModalVisible(false);
                }}
              />
            </View>
              </ScrollView>
            </Pressable>
          </KeyboardAvoidingView>
          {sheetZoomUri ? (
            <View style={styles.sheetZoomOverlay} pointerEvents="box-none">
              <Pressable
                style={styles.sheetZoomBackdrop}
                onPress={() => setSheetZoomUri(null)}
              />
              <Pressable
                style={styles.sheetZoomClose}
                onPress={closeSheetViewer}
                hitSlop={12}
                pointerEvents="auto">
                <ThemedText style={styles.sheetZoomCloseText}>{t('common.close')}</ThemedText>
              </Pressable>
              <View style={styles.sheetZoomContent} pointerEvents="auto">
                {isVideoUri(sheetZoomUri) ? (
                  <Video
                    source={{ uri: sheetZoomUri }}
                    style={styles.sheetZoomVideo}
                    useNativeControls
                    resizeMode={ResizeMode.CONTAIN}
                  />
                ) : (
                  <ScrollView
                    style={styles.sheetZoomScroll}
                    contentContainerStyle={styles.sheetZoomScrollContent}
                    minimumZoomScale={1}
                    maximumZoomScale={3}
                    centerContent
                    showsHorizontalScrollIndicator={false}
                    showsVerticalScrollIndicator={false}>
                    <Image source={{ uri: sheetZoomUri }} style={styles.sheetZoomImage} resizeMode="contain" />
                  </ScrollView>
                )}
              </View>
            </View>
          ) : null}
        </View>
      </Modal>
      <ZoomImageModal
        uri={zoomUri}
        visible={Boolean(zoomUri)}
        onClose={() => setZoomUri(null)}
      />
    </>
  );
}

function formatDate(value: string) {
  try {
    return new Date(value).toLocaleString();
  } catch {
    return value;
  }
}

async function handlePickPhoto(
  setter: (value: string | null) => void,
  onAdd?: (uris: string[]) => void
) {
  const result = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: getMediaTypes(),
    quality: 1,
    allowsMultipleSelection: true,
    selectionLimit: 0,
  });
  if (result.canceled) return;
  const uris = (result.assets ?? []).map((asset) => asset.uri).filter(Boolean) as string[];
  if (uris.length === 0) return;
  console.log('[Fields] Picked media:', uris);
  setter(uris[0]);
  onAdd?.(uris);
}

async function handleTakePhoto(
  setter: (value: string | null) => void,
  onError?: (msg: string) => void
) {
  try {
    const permission = await ImagePicker.requestCameraPermissionsAsync();
    if (!permission.granted) {
      onError?.('cameraDenied');
      return;
    }
    const result = await ImagePicker.launchCameraAsync({
      mediaTypes: getMediaTypes(),
      quality: 1,
    });
    if (result.canceled) return;
    const asset = result.assets[0];
    console.log('[Fields] Captured media:', asset.uri);
    setter(asset.uri);
  } catch {
    onError?.('cameraError');
  }
}

function getMediaTypes() {
  const mediaType = (ImagePicker as {
    MediaType?: { Image?: unknown; Images?: unknown; Video?: unknown; Videos?: unknown };
  }).MediaType;
  const imageType = mediaType?.Image ?? mediaType?.Images;
  const videoType = mediaType?.Video ?? mediaType?.Videos;
  if (imageType && videoType) {
    return [imageType, videoType];
  }
  return imageType ?? videoType ?? ['images', 'videos'];
}

function isVideoUri(uri: string) {
  return /\.(mp4|mov|m4v|webm|avi|mkv)(\?.*)?$/i.test(uri);
}

function normalizeMediaUri(uri?: string | null) {
  if (typeof uri !== 'string') return null;
  const trimmed = uri.trim();
  return trimmed ? trimmed : null;
}

function uniqueMediaUris(uris: string[]) {
  const seen = new Set<string>();
  const result: string[] = [];
  for (const uri of uris) {
    if (!uri || seen.has(uri)) continue;
    seen.add(uri);
    result.push(uri);
  }
  return result;
}


const styles = StyleSheet.create({
  hero: {
    backgroundColor: '#E8E6DA',
    aspectRatio: 16 / 9,
    width: '100%',
  },
  heroImage: {
    width: '100%',
    height: '100%',
  },
  titleContainer: {
    gap: 8,
    paddingHorizontal: 16,
    paddingVertical: 12,
  },
  section: {
    gap: 8,
    marginBottom: 16,
    paddingHorizontal: 16,
  },
  newButton: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 8,
    borderRadius: 10,
    borderWidth: 1,
    borderColor: '#B9B9B9',
    paddingHorizontal: 12,
    paddingVertical: 10,
    alignSelf: 'flex-start',
  },
  newButtonText: {
    fontSize: 15,
    fontWeight: '600',
  },
  card: {
    borderRadius: 12,
    borderWidth: 1,
    borderColor: '#C6C6C6',
    padding: 12,
    marginHorizontal: 16,
    gap: 6,
    backgroundColor: '#FFFFFF',
  },
  meta: {
    opacity: 0.7,
  },
  input: {
    borderRadius: 10,
    borderWidth: 1,
    borderColor: '#B9B9B9',
    paddingHorizontal: 12,
    paddingVertical: 10,
    fontSize: 15,
  },
  requiredMark: {
    color: '#C0392B',
    fontWeight: '700',
  },
  errorText: {
    color: '#C0392B',
    fontSize: 12,
  },
  photoPreview: {
    width: '100%',
    height: 200,
    borderRadius: 12,
  },
  buttonRow: {
    alignSelf: 'flex-start',
    flexDirection: 'row',
    gap: 8,
    alignItems: 'center',
    width: '100%',
  },
  metaEnd: {
    marginLeft: 'auto',
    opacity: 0.7,
    fontSize: 12,
  },
  cancelRow: {
    marginTop: 8,
  },
  modalActions: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    gap: 12,
  },
  sheetOverlay: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.3)',
    justifyContent: 'flex-end',
  },
  sheetBackdrop: {
    ...StyleSheet.absoluteFillObject,
  },
  sheet: {
    borderTopLeftRadius: 16,
    borderTopRightRadius: 16,
    borderWidth: 1,
    borderColor: '#C6C6C6',
    padding: 16,
    backgroundColor: '#FFFFFF',
    gap: 10,
    maxHeight: '85%',
  },
  sheetContent: {
    gap: 10,
    paddingBottom: 80,
  },
  sheetZoomOverlay: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    backgroundColor: 'rgba(0,0,0,0.85)',
    justifyContent: 'center',
    alignItems: 'center',
    zIndex: 10,
    elevation: 10,
  },
  sheetZoomBackdrop: {
    ...StyleSheet.absoluteFillObject,
    zIndex: 0,
  },
  sheetZoomContent: {
    width: '100%',
    height: '100%',
    paddingHorizontal: 16,
    paddingTop: 24,
    paddingBottom: 24,
    justifyContent: 'center',
    zIndex: 1,
  },
  sheetZoomClose: {
    position: 'absolute',
    top: 24,
    right: 16,
    zIndex: 2,
    backgroundColor: 'rgba(0,0,0,0.6)',
    paddingHorizontal: 12,
    paddingVertical: 6,
    borderRadius: 14,
  },
  sheetZoomCloseText: {
    color: '#FFFFFF',
    fontWeight: '600',
  },
  sheetZoomScroll: {
    flex: 1,
  },
  sheetZoomScrollContent: {
    flexGrow: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  sheetZoomImage: {
    width: '100%',
    height: '100%',
  },
  sheetZoomVideo: {
    width: '100%',
    height: '100%',
  },
  keyboardAvoid: {
    width: '100%',
    flex: 1,
    justifyContent: 'flex-end',
  },
  separator: {
    height: 12,
  },
  footer: {
    height: 24,
  },
  photoRow: {
    flexDirection: 'row',
    gap: 8,
  },
  photoPlaceholder: {
    opacity: 0.6,
  },
  mediaPlaceholder: {
    opacity: 0.8,
    fontStyle: 'italic',
  },
  videoPreview: {
    width: '100%',
    height: 200,
    borderRadius: 12,
    backgroundColor: '#1C1C1C',
  },
  mediaStrip: {
    marginTop: 6,
  },
  mediaChip: {
    width: 72,
    height: 72,
    borderRadius: 10,
    marginRight: 8,
    overflow: 'hidden',
    backgroundColor: '#E6E1D4',
    alignItems: 'center',
    justifyContent: 'center',
  },
  mediaThumb: {
    width: '100%',
    height: '100%',
  },
  removeBadge: {
    position: 'absolute',
    top: 4,
    right: 4,
    backgroundColor: 'rgba(0,0,0,0.6)',
    width: 18,
    height: 18,
    borderRadius: 9,
    alignItems: 'center',
    justifyContent: 'center',
  },
  removeBadgeText: {
    color: '#FFFFFF',
    fontSize: 12,
    lineHeight: 14,
    fontWeight: '700',
  },
  videoThumb: {
    width: '100%',
    height: '100%',
    backgroundColor: '#1C1C1C',
    alignItems: 'center',
    justifyContent: 'center',
  },
  videoThumbText: {
    color: '#FFFFFF',
    fontSize: 18,
    fontWeight: '700',
  },
});
