import { AntDesign, FontAwesome, Ionicons, MaterialCommunityIcons } from '@expo/vector-icons'
import { Block, ConfirmModal, Text, Toast, VideoBox } from '@share/components'
import Img from '@share/components/Img'
import { FlashList } from '@shopify/flash-list'
import * as ImagePicker from 'expo-image-picker'
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { Platform, ScrollView, View } from 'react-native'
import Animated, { Easing, useAnimatedStyle, useSharedValue, withRepeat, withTiming } from 'react-native-reanimated'
import { useSafeAreaInsets } from 'react-native-safe-area-context'

import { imgPicker } from '@/@share/apis'
import { useBleExplorer } from '@/ble'
import BannerSection from '@/components/BannerSection'
import { useFileUpload } from '@/hooks/actions/use-file-upload'
import { useTemplateActions } from '@/hooks/actions/use-template-actions'
import { useAuth } from '@/hooks/core/use-auth'
import { useTemplateGenerations } from '@/hooks/data/use-template-generations'
import { screenWidth } from '@/utils'
import { aniStorage } from '@/utils/aniStorage'
import { cn } from '@/utils/cn'

// ============ 小组件 ============
const SpinningLoader = memo(() => {
  const rotation = useSharedValue(0)

  useEffect(() => {
    rotation.value = withRepeat(withTiming(360, { duration: 1000, easing: Easing.linear }), -1, false)
  }, [])

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ rotate: `${rotation.value}deg` }],
  }))

  return (
    <Animated.View style={animatedStyle}>
      <FontAwesome color="#FFE500" name="circle-o-notch" size={20} />
    </Animated.View>
  )
})

const DeviceItem = memo(({ device, onConnectToggle }: { device: any; onConnectToggle: (device: any) => void }) => {
  const { name = 'Unknown Device', id, connected: isConnected } = device

  return (
    <Block className="relative mb-[16px] flex-row items-center overflow-hidden border-[3px] border-black bg-white p-[16px] shadow-large-black">
      {isConnected && <Block className="absolute inset-y-0 left-0 w-[16px] border-r-[3px] border-black bg-accent" />}

      <Block className="size-[48px] items-center justify-center border-[3px] border-black bg-gray-100 shadow-soft-black-10">
        <Ionicons color="black" name="phone-portrait-outline" size={24} />
      </Block>

      <Block className="relative z-10 ml-[16px] flex-1 flex-row items-center justify-between gap-[16px]">
        <Block className="flex-1">
          <Block className="flex-1 flex-row gap-[8px]">
            <Text className="break-words text-[18px] font-[900] italic">{name}</Text>
          </Block>
          <Block className="mt-[4px] flex-row gap-[8px]">
            <Text
              className={`border-2 border-black px-[6px] text-[10px] font-[900] italic ${isConnected ? 'bg-black text-accent' : 'bg-gray-200 text-gray-500'}`}
            >
              {isConnected ? '已连接' : '未连接'}
            </Text>
          </Block>
        </Block>

        <Block className="relative z-10 items-center">
          <Block
            className={`h-[40px] items-center justify-center border-[3px] border-black px-[16px] text-[12px] font-[900] italic ${isConnected ? 'bg-accent text-black shadow-medium-black' : 'bg-white text-black shadow-medium-gray'}`}
            onClick={() => onConnectToggle(device)}
          >
            <Text className="text-[12px] font-[900] italic">{isConnected ? '已连接' : '连接'}</Text>
          </Block>
        </Block>
      </Block>
    </Block>
  )
})

const GridItem = memo(
  ({
    post,
    isSelected,
    isSelectionMode,
    itemWidth,
    isVisible,
    onSelect,
  }: {
    post: any
    isSelected: boolean
    isSelectionMode: boolean
    itemWidth: number
    isVisible: boolean
    onSelect: (post: any) => void
  }) => {
    return (
      <Block className="relative" onClick={() => onSelect(post)}>
        <Block
          className={`relative overflow-hidden border-2 ${isSelected ? 'shadow-[0px_0px_0px_4px_#FFE500]' : 'shadow-hard-black'} ${isSelected ? 'border-accent' : 'border-black'}`}
          style={{ transform: [{ skewX: '-6deg' }], height: itemWidth, width: itemWidth }}
        >
          <Block style={{ height: itemWidth, width: itemWidth }}>
            <Img className="size-full" src={post.imageUrl} />
          </Block>
          {isSelected && <Block className="absolute inset-0 border-[3px] border-accent" />}

          {isSelectionMode && (
            <Block
              className="absolute inset-0 z-30 items-center justify-center"
              style={{ transform: [{ skewX: '6deg' }] }}
            >
              <Block
                className={`size-[32px] items-center justify-center rounded-full border-[3px] border-black ${isSelected ? 'bg-accent' : 'bg-white/50'}`}
              >
                <Ionicons color="black" name="checkmark" size={20} />
              </Block>
            </Block>
          )}
        </Block>
      </Block>
    )
  },
)

const FilterButtons = memo(
  ({ isSelectionMode, onToggleSelectionMode }: { isSelectionMode: boolean; onToggleSelectionMode: () => void }) => {
    return (
      <Block className="flex flex-row items-center justify-between" style={{ marginVertical: 16 }}>
        <Block className="flex-row">
          {['我的生成'].map((label) => {
            return (
              <Block
                key={label}
                className={`-skew-x-3 border-2 border-black bg-black px-[16px] py-[4px] shadow-small-accent`}
              >
                <Text className={`text-[10px] font-[900] italic text-accent`}>{label}</Text>
              </Block>
            )
          })}
        </Block>
        <Block
          className={`border-2 border-black px-[16px] py-[6px] shadow-medium-black ${isSelectionMode ? 'bg-[#e61e25] text-white' : 'bg-accent text-black'}`}
          onClick={onToggleSelectionMode}
        >
          <Text className="text-[12px] font-[900] italic">{isSelectionMode ? '取消' : '管理'}</Text>
        </Block>
      </Block>
    )
  },
)

const SelectionBar = memo(
  ({
    isSelectionMode,
    selectedCount,
    onSelectAll,
    onDelete,
  }: {
    isSelectionMode: boolean
    selectedCount: number
    onSelectAll: () => void
    onDelete: () => void
  }) => {
    const insets = useSafeAreaInsets()
    if (!isSelectionMode) return null

    return (
      <Block className="absolute inset-x-[16px] bottom-[96px] z-50" style={{ paddingBottom: insets.bottom }}>
        <Block className="-skew-x-3 flex-row items-center justify-between border-[3px] border-black bg-white p-[12px] shadow-large-black">
          <Block className="skew-x-3 flex-row items-center gap-[12px] pl-[8px]">
            <Text className="text-[14px] font-[900] italic">已选: {selectedCount}</Text>
            <Block className="text-[12px] underline" onClick={onSelectAll}>
              <Text className="text-[12px] font-[700]">全选</Text>
            </Block>
          </Block>
          <Block
            className={`skew-x-3 flex-row items-center space-x-[8px] border-2 border-black px-[16px] py-[8px] font-[[90]0] text-[14px] shadow-medium-black${selectedCount > 0 ? 'bg-[#e61e25] text-white' : 'bg-gray-200 text-gray-400'}`}
            onClick={onDelete}
          >
            <Ionicons color="black" name="trash-outline" size={16} />
            <Text className="text-[14px] font-[900]">{selectedCount > 0 ? '删除' : '删除'}</Text>
          </Block>
        </Block>
      </Block>
    )
  },
)

const FABButtons = memo(
  ({ onGenAgain, onSync, canSync }: { onGenAgain: () => void; onSync: () => void; canSync: boolean }) => {
    const insets = useSafeAreaInsets()
    return (
      <Block className="absolute inset-x-[16px] bottom-[96px] z-40" style={{ paddingBottom: insets.bottom }}>
        <Block className="w-full flex-row gap-[12px]">
          <Block className="flex-1 -skew-x-6 shadow-large-black">
            <Block
              className={cn`relative h-[56px] items-center justify-center overflow-hidden border-[2px] border-black bg-[#e61e25] shadow-large-accent`}
              onClick={onGenAgain}
            >
              <Block className="z-10 skew-x-6 flex-row items-center gap-[8px]">
                <MaterialCommunityIcons color="white" name="star-four-points" size={20} />
                <Text className="font-[bol]d text-[16px] italic text-white">再次生成</Text>
              </Block>
            </Block>
          </Block>

          <Block className="flex-1 -skew-x-6 shadow-large-accent">
            <Block
              className={cn`relative h-[56px] items-center justify-center overflow-hidden border-[2px] border-black bg-black`}
              onClick={onSync}
            >
              <Block className="z-10 flex-row items-center gap-[8px]">
                <Ionicons color={'white'} name="refresh" size={20} />
                <Text className={cn`font-[bol]d bg-black text-[16px] italic text-white`}>同步</Text>
              </Block>
            </Block>
          </Block>
        </Block>
      </Block>
    )
  },
)

// ============ 主要组件部分 ============
const HeaderBanner = memo(({ connectedDevice, onPick }: { connectedDevice: any; onPick: () => void }) => {
  return (
    <Block className="relative z-40 flex-row items-center justify-between py-[12px]">
      <Block className="flex-row items-center gap-[8px] border-2 border-white bg-black py-[4px] shadow-hard-accent">
        <Block className={`size-[8px] ${connectedDevice ? 'bg-accent' : 'bg-red-500'}`} />
        <Text className="text-[12px] font-[900] tracking-[1px] text-white">
          {connectedDevice ? '设备已连接' : '设备离线'}
        </Text>
      </Block>
      <Block
        className="h-[40px] flex-row items-center justify-center gap-[8px] border-[3px] border-black bg-white px-[12px] shadow-hard-black"
        onClick={onPick}
      >
        <Ionicons color="black" name="cloud-upload-outline" size={18} />
        <Text className="text-[12px] font-[900] italic text-black">上传本地</Text>
      </Block>
    </Block>
  )
})

const TopCircleSection = memo(
  ({
    connectedDevice,
    onStartConnect,
    selectedItem,
  }: {
    connectedDevice: any
    onStartConnect: () => void
    selectedItem: any
  }) => {
    const outerRotate = useSharedValue(0)
    useEffect(() => {
      outerRotate.value = withRepeat(withTiming(360, { duration: 12000, easing: Easing.linear }), -1, false)
    }, [])
    const outerRingStyle = useAnimatedStyle(() => ({
      transform: [{ rotate: `${outerRotate.value}deg` }],
    }))

    return (
      <Block className="relative z-10 items-center">
        <Block className="relative my-[24px] flex w-full flex-row items-center justify-between">
          <Block
            className={`w-[48px] items-center justify-center gap-[4px] border-[3px] border-black py-[12px] shadow-hard-black-50 ${connectedDevice ? 'bg-accent' : 'bg-white'}`}
            onClick={onStartConnect}
          >
            <Ionicons
              color={connectedDevice ? 'black' : '#6B7280'}
              name={connectedDevice ? 'wifi' : 'wifi-outline'}
              size={20}
            />
            <Text className="text-[10px] font-[900] italic">{connectedDevice ? '已连接' : '选择设备'}</Text>
          </Block>
          <Block className="relative size-[256px] items-center justify-center">
            <Block
              animated
              className="absolute inset-[-12px] rounded-full border-[3px] border-dashed border-black opacity-30"
              style={outerRingStyle}
            />
            <Block>
              <GalleryRenderer selectedItem={selectedItem} />
              {connectedDevice && (
                <Block className="absolute inset-0 items-center justify-center">
                  {/* <Ionicons name="desktop-outline" size={48} color="white" /> */}
                  <Text className="border border-white bg-black px-[12px] py-[2px] text-[12px] font-[900] italic text-white">
                    离线模式
                  </Text>
                </Block>
              )}
            </Block>
          </Block>
          <Block className="h-[10px] w-[48px]" />
        </Block>
      </Block>
    )
  },
)

const GalleryRenderer = memo(({ selectedItem }: { selectedItem: any }) => {
  const url = selectedItem?.url || selectedItem.imageUrl
  console.log('GalleryRenderer------------', url)

  if (!url) return null

  const Width = 256
  return (
    <View
      className="relative z-10 border-4 border-black"
      style={{ width: Width, height: Width, borderRadius: Width, overflow: 'hidden' }}
    >
      <VideoBox style={{ width: Width, height: Width }} url={url} width={Width} />
    </View>
  )
})

const ManagerView = memo(
  ({
    viewState,
    onBack,
    onConnectToggle,
  }: {
    viewState: string
    onBack: () => void
    onConnectToggle: (device: any) => void
  }) => {
    const { discoveredDevices } = useBleExplorer()

    if (viewState !== 'manager') return null

    return (
      <Block className="absolute inset-0" style={{ zIndex: 100 }}>
        <Block className="relative flex-1 bg-paper">
          <Block className="flex-row items-center justify-between px-[16px] py-[12px]">
            <Block
              className="size-[40px] items-center justify-center border-[3px] border-black bg-white shadow-medium-black"
              onClick={onBack}
            >
              <Ionicons color="black" name="chevron-back" size={24} />
            </Block>
            <Text className="text-[20px] font-[900] italic tracking-[-0.5px]">设备管理</Text>
            <Block className="size-[40px] items-center justify-center bg-black/0">{/* 空占位符 */}</Block>
          </Block>

          <ScrollView className="relative flex-1 bg-paper">
            <Block className="p-[16px]">
              {discoveredDevices
                .filter((i) => i.name)
                .map((device) => (
                  <DeviceItem key={device.id} device={device} onConnectToggle={onConnectToggle} />
                ))}
            </Block>
            <Block className="h-[200px] w-full" />
          </ScrollView>
        </Block>
      </Block>
    )
  },
)

// ============ 主组件 ============
const Sync = () => {
  const { user } = useAuth()
  const { data: generationsData, loading: generationsLoading, load: loadGenerations } = useTemplateGenerations()
  const { uploadFile, loading: uploadLoading } = useFileUpload()
  const { runTemplate, batchDeleteGenerations, loading: actionLoading } = useTemplateActions()

  const [viewState, setViewState] = useState<'home' | 'manager' | 'scanner'>('home')
  const [selectedItem, setSelectedItem] = useState({} as any)
  const [isSelectionMode, setIsSelectionMode] = useState(false)
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set())

  const {
    connectedDevice,

    startScan,
    stopScan,
    connectToDevice,
    disconnectDevice,

    transferMediaSingle,
  } = useBleExplorer()

  const itemWidth = Math.floor((screenWidth - 12 * 2 - 12 * 2) / 3)

  // 加载生成记录
  useEffect(() => {
    if (user?.id) {
      loadGenerations()
    }
  }, [user?.id, loadGenerations])

  // 将生成记录转换为 posts 格式
  const posts = useMemo(() => {
    const generations = generationsData?.data || []
    return generations.map((gen: any) => ({
      id: gen.id,
      imageUrl: Array.isArray(gen.resultUrl) ? gen.resultUrl[0] : gen.resultUrl,
      originalUrl: gen.originalUrl,
      templateId: gen.templateId,
      type: gen.type,
      status: gen.status,
      createdAt: gen.createdAt,
      title: `生成-${gen.id.slice(0, 6)}`,
      rank: 'S',
      author: user?.name || 'User',
      avatarUrl:
        user?.image || 'https://image.pollinations.ai/prompt/cool%20anime%20boy%20avatar%20hoodie?seed=123&nologo=true',
    }))
  }, [generationsData, user])

  useEffect(() => {
    if (!selectedItem?.id && posts.length > 0) {
      const firstItem = posts[0]

      const newItem = {
        id: firstItem.id,
        imageUrl: firstItem.imageUrl,
        url: firstItem.imageUrl,
        originalUrl: firstItem.originalUrl,
      }
      setSelectedItem(newItem)
    }
  }, [posts])

  const viewableIds = useRef<Set<string>>(new Set(posts.map((p: any) => p.id)))

  // 事件处理函数
  const handleConnectToggle = useCallback(
    async (item: any) => {
      if (item.connected) {
        disconnectDevice()
      } else {
        await disconnectDevice()
        Toast.showLoading({
          title: '连接中...',
          duration: 30e3,
        })
        connectToDevice(item)
          .then(() => {
            console.log('设备连接成功')
          })
          .catch(() => {
            Toast.show({
              title: '设备连接失败',
            })
          })
          .finally(() => {
            Toast.hideLoading()
          })
      }
    },
    [connectToDevice, disconnectDevice],
  )

  const canSync = useMemo(() => {
    return !!connectedDevice?.id && !!selectedItem?.imageUrl
  }, [connectedDevice, selectedItem])

  const handleSync = useCallback(async () => {
    // await aniStorage.set('test_url', { test: 'data' })
    console.log(
      'aniStorage.has----------------',
      await aniStorage.has('test_url'),
      // await aniStorage.delete('test_url'),
      // await aniStorage.get('test_url'),
    )

    if (!canSync) {
      Toast.show({ title: '请先连接设备' })
      return
    }

    Toast.show({
      renderContent: () => (
        <Block
          className="flex w-full flex-row items-center justify-center border-[3px] border-white bg-black"
          style={{ paddingVertical: 14, transform: [{ skewX: '-6deg' }] }}
        >
          <SpinningLoader />
          <Block style={{ marginLeft: 8 }}>
            <Text className="font-[bla]ck text-[14px] italic text-white">正在同步文件...</Text>
          </Block>
        </Block>
      ),
      duration: 0,
    })

    transferMediaSingle(selectedItem?.imageUrl)
      .then(() => {
        Toast.show({ title: '同步成功' })
      })
      .catch(() => {
        Toast.hideLoading()
        Toast.show({ title: '同步失败' })
      })
  }, [canSync, selectedItem, transferMediaSingle])

  const handlePick = useCallback(async () => {
    const assetList = await imgPicker({ maxImages: 1, type: ImagePicker.MediaTypeOptions.All, resultType: 'asset' })

    if (!assetList?.length) return

    const result = assetList[0] as any

    Toast.showLoading({ title: '上传中...', duration: 30e3 })

    const file = {
      name: result.fileName,
      type: result.mimeType || 'image/jpeg',
      uri: Platform.OS === 'android' ? result.uri : result.uri.replace('file://', ''),
    }
    const formData = new FormData()
    formData.append('file', file as any)

    const { url, error } = await uploadFile(file as any)

    Toast.hideLoading()

    if (error || !url) {
      Toast.show({ title: '上传失败' })
      return
    }

    const newItem = {
      id: `local-${Date.now()}`,
      // type: isVideo ? 'video' : 'image',
      imageUrl: url,
      url,
      originalUrl: url,
      // ...(typeof asset === 'object' ? asset : {}),
    }

    setSelectedItem(newItem)

    // // 如果设备已连接，询问是否同步
    // 先预览不直接同步上传
    // if (connectedDevice?.id) {
    //   Toast.showModal(
    //     <ConfirmModal
    //       content={<Text className="text-[14px] leading-relaxed text-gray-800">文件已上传，是否立即同步到设备？</Text>}
    //       onConfirm={() => {
    //         Toast.hideModal()
    //         handleSync()
    //       }}
    //       onCancel={() => Toast.hideModal()}
    //     />,
    //   )
    // } else {
    //   Toast.show({ title: '上传成功' })
    // }
  }, [uploadFile, connectedDevice, handleSync])

  const startConnect = useCallback(() => {
    setViewState('manager')
    startScan()
  }, [startScan])

  const handleGenAgain = useCallback(() => {
    if (!selectedItem?.templateId) {
      Toast.show({ title: '请先选择一个生成记录' })
      return
    }

    Toast.showModal(
      <ConfirmModal
        content={
          <Text className="font-[bol]d text-[14px] leading-relaxed text-gray-800">
            生成同款风格将消耗 <Text className="font-[bla]ck mx-[4px] text-[20px] italic text-[#e61e25]">2 Goo</Text>{' '}
            算力。
          </Text>
        }
        onCancel={() => Toast.hideModal()}
        onConfirm={handleGenAgainConfirm}
      />,
    )
  }, [selectedItem])

  const handleGenAgainConfirm = useCallback(async () => {
    if (!selectedItem?.templateId || !selectedItem?.originalUrl) return

    Toast.hideModal()
    Toast.show({
      renderContent: () => (
        <Block
          className="flex w-full flex-row items-center justify-center border-[3px] border-white bg-black"
          style={{ paddingVertical: 14, transform: [{ skewX: '-6deg' }] }}
        >
          <SpinningLoader />
          <Block style={{ marginLeft: 8 }}>
            <Text className="font-[bla]ck text-[14px] italic text-white">正在生成中...</Text>
          </Block>
        </Block>
      ),
      duration: 0,
    })

    const { generationId, error } = await runTemplate({
      templateId: selectedItem.templateId,
      data: {},
      originalUrl: selectedItem.originalUrl,
    })

    Toast.hideLoading()

    if (error || !generationId) {
      Toast.show({ title: error?.message || '生成失败' })
      return
    }

    Toast.show({
      renderContent: () => (
        <Block
          className="flex w-full flex-row items-center justify-center border-[3px] border-white bg-black"
          style={{ paddingVertical: 14, transform: [{ skewX: '-6deg' }] }}
        >
          <AntDesign color="white" name="check-circle" size={20} />
          <Block style={{ marginLeft: 8 }}>
            <Text className="font-[bla]ck text-[14px] italic text-white">生成成功</Text>
          </Block>
        </Block>
      ),
    })

    // 刷新列表
    if (user?.id) {
      loadGenerations()
    }
  }, [selectedItem, runTemplate, user?.id, loadGenerations])

  const toggleSelectionMode = useCallback(() => {
    setIsSelectionMode((v) => !v)
    setSelectedIds(new Set())
  }, [])

  const handleItemSelect = useCallback(
    (post: any) => {
      if (isSelectionMode) {
        const next = new Set(selectedIds)
        if (next.has(post.id)) next.delete(post.id)
        else next.add(post.id)
        setSelectedIds(next)
      } else {
        setSelectedItem(post)
      }
    },
    [isSelectionMode, selectedIds],
  )

  const handleDelete = useCallback(async () => {
    if (selectedIds.size === 0) return

    const { success, error } = await batchDeleteGenerations(Array.from(selectedIds))

    if (error || !success) {
      Toast.show({ title: error?.message || '删除失败' })
      return
    }

    Toast.show({ title: `成功删除 ${selectedIds.size} 个生成记录` })

    // 刷新列表
    if (user?.id) {
      await loadGenerations()
    }

    setSelectedIds(new Set())
    setIsSelectionMode(false)
  }, [selectedIds, batchDeleteGenerations, user?.id, loadGenerations])

  const selectAll = useCallback(() => {
    if (selectedIds.size === posts.length) {
      setSelectedIds(new Set())
    } else {
      setSelectedIds(new Set(posts.map((p: any) => p.id)))
    }
  }, [posts, selectedIds.size])

  const onViewableItemsChanged = useCallback((params: any) => {
    const { viewableItems } = params
    viewableIds.current = new Set(viewableItems.map((v: any) => v.item.id))
  }, [])

  const renderHeader = useMemo(
    () => (
      <Block className="z-10">
        <HeaderBanner connectedDevice={connectedDevice} onPick={handlePick} />
        <TopCircleSection connectedDevice={connectedDevice} selectedItem={selectedItem} onStartConnect={startConnect} />
        <FilterButtons isSelectionMode={isSelectionMode} onToggleSelectionMode={toggleSelectionMode} />
      </Block>
    ),
    [connectedDevice, handlePick, startConnect, isSelectionMode, toggleSelectionMode, selectedItem],
  )

  const renderGridItem = useCallback(
    ({ item: post }: { item: any }) => {
      const isSelected = isSelectionMode ? selectedIds.has(post.id) : selectedItem?.id === post.id
      const isVisible = viewableIds.current.has(post.id)

      return (
        <GridItem
          isSelected={isSelected}
          isSelectionMode={isSelectionMode}
          isVisible={isVisible}
          itemWidth={itemWidth}
          post={post}
          onSelect={handleItemSelect}
        />
      )
    },
    [isSelectionMode, selectedIds, selectedItem, itemWidth, handleItemSelect],
  )

  return (
    <Block className="relative flex-1">
      <BannerSection />

      <Block className="z-10 flex-1">
        <FlashList
          removeClippedSubviews
          contentContainerStyle={{ paddingHorizontal: 12, paddingBottom: 200 }}
          data={posts}
          getItemType={() => 'row'}
          ItemSeparatorComponent={() => <Block style={{ height: 6 }} />}
          keyExtractor={(item: any) => item?.id}
          ListHeaderComponent={renderHeader}
          numColumns={3}
          renderItem={renderGridItem}
          viewabilityConfig={{ itemVisiblePercentThreshold: 60 }}
          onViewableItemsChanged={onViewableItemsChanged}
        />
      </Block>

      <FABButtons canSync={canSync} onGenAgain={handleGenAgain} onSync={handleSync} />

      <SelectionBar
        isSelectionMode={isSelectionMode}
        selectedCount={selectedIds.size}
        onDelete={handleDelete}
        onSelectAll={selectAll}
      />

      <ManagerView
        viewState={viewState}
        onConnectToggle={handleConnectToggle}
        onBack={() => {
          setViewState('home')
          stopScan()
        }}
      />
    </Block>
  )
}

export default memo(Sync)
