import { Ionicons } from '@expo/vector-icons'
import { Block, ConfirmModal, ListEmpty, Text, Toast, VideoBox } from '@share/components'
import { FlashList } from '@shopify/flash-list'
import { LinearGradient } from 'expo-linear-gradient'
import { router, useFocusEffect } from 'expo-router'
import { observer } from 'mobx-react-lite'
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { ActivityIndicator, RefreshControl, TextInput } from 'react-native'

import BannerSection from '@/components/BannerSection'
import { useTemplateActions } from '@/hooks/actions/use-template-actions'
import { useTemplates } from '@/hooks/data'
import { useFavoriteTemplates } from '@/hooks/data/use-favorite-templates'
import { userBalanceStore, userStore } from '@/stores'
import { screenWidth } from '@/utils'
import { cn } from '@/utils/cn'

const CATEGORY_ID = process.env.EXPO_PUBLIC_INDEX_GROUP_ID
const ITEM_WIDTH = Math.floor((screenWidth - 24 - 12 * 2) / 3)
const PAGE_SIZE = 21

type MediaItem = {
  id: string
  type: 'image' | 'video'
  url: string
  poster?: string
  likeCount?: number
  price: number
  title?: string
  authorName?: string
}
type ActiveTab = 'gen' | '' | 'new' | 'like'

/** =========================
 * Entry page
 * ========================= */

const Index = observer(function Index() {
  // 从MobX Store获取用户信息
  const { user, isAuthenticated } = userStore as typeof userStore
  const { execute: loadTemplates } = useTemplates()
  const { execute: loadFavorites } = useFavoriteTemplates()
  const { runTemplate } = useTemplateActions()

  // 使用MobX Store中的余额信息
  const { balance } = userBalanceStore

  /** ================= 状态 ================= */

  const [activeTab, setActiveTab] = useState<ActiveTab>('')
  const [isSearchOpen, setIsSearchOpen] = useState(false)

  const [allItems, setAllItems] = useState<MediaItem[]>([])
  const [selectedItem, setSelectedItem] = useState<MediaItem | null>(null)

  const [refreshing, setRefreshing] = useState(false)
  const [loadingMore, setLoadingMore] = useState(false)
  const [hasMore, setHasMore] = useState(true)

  /** ================= refs（核心） ================= */

  const queryRef = useRef({
    page: 1,
    pageSize: PAGE_SIZE,
    search: '',
    tab: '' as ActiveTab,
  })

  const loadingRef = useRef(false)
  const firstLoadDoneRef = useRef(false)

  /** ================= 工具函数 ================= */

  type TemplateData = {
    id: string
    previewUrl?: string
    coverImageUrl?: string
    likeCount?: number
    price?: number
    title?: string
    isDeleted?: boolean
  }

  const transformTemplateToMediaItem = useCallback((template: TemplateData): MediaItem => {
    const isVideo = template.previewUrl?.includes('.mp4')
    return {
      id: template.id,
      type: isVideo ? 'video' : 'image',
      url: isVideo ? (template.previewUrl ?? '') : template.coverImageUrl || template.previewUrl || '',
      poster: isVideo ? template.coverImageUrl : undefined,
      likeCount: template.likeCount || 0,
      price: template.price || 0,
      authorName: template?.user?.name || '未知作者',
      title: template.title || '',
    }
  }, [])

  /** ================= 统一请求函数 ================= */

  const fetchList = async (mode: 'init' | 'refresh' | 'loadMore') => {
    if (loadingRef.current) return
    if (mode === 'loadMore' && !hasMore) return

    loadingRef.current = true
    if (mode === 'loadMore') {
      setLoadingMore(true)
    } else {
      setRefreshing(true)
    }

    try {
      const { page, pageSize, search, tab } = queryRef.current
      let newItems: MediaItem[] = []

      if (tab === 'like') {
        if (!isAuthenticated) {
          setHasMore(false)
          newItems = []
        } else {
          const { data } = await loadFavorites({ page, limit: pageSize })
          newItems =
            data?.favorites
              ?.filter((f) => f.template && !(f.template as TemplateData).isDeleted)
              .map((f) => transformTemplateToMediaItem(f.template as TemplateData)) || []
        }
      } else {
        const sortBy = tab === 'new' ? 'createdAt' : 'likeCount'
        const { data } = await loadTemplates({
          page,
          limit: pageSize,
          sortBy,
          sortOrder: 'desc',
          search,
          categoryId: CATEGORY_ID,
        })
        newItems = data?.templates?.map(transformTemplateToMediaItem) || []
      }

      if (newItems.length < pageSize) {
        setHasMore(false)
      }

      const updatedItems = mode === 'loadMore' ? [...allItems, ...newItems] : newItems

      setAllItems(updatedItems)
    } catch (e) {
      console.error('fetchList error:', e)
      setHasMore(false)
    } finally {
      loadingRef.current = false
      // 标记首次（或第一页）加载已完成，避免 FlashList 首次渲染触发 onEndReached
      const currentPage = queryRef.current.page
      if (currentPage === 1) {
        firstLoadDoneRef.current = true
      }
      setRefreshing(false)
      setLoadingMore(false)
    }
  }

  /** ================= tab 切换（抽象后的重点） ================= */

  const changeTab = useCallback((tab: ActiveTab) => {
    queryRef.current = {
      ...queryRef.current,
      tab,
      page: 1,
    }
    setHasMore(true)
    firstLoadDoneRef.current = false
    fetchList('init')
  }, [])

  /** ================= 搜索 ================= */

  const handleSearch = useCallback((text: string) => {
    queryRef.current = {
      ...queryRef.current,
      search: text,
      page: 1,
    }
    setHasMore(true)
    firstLoadDoneRef.current = false
    fetchList('refresh')
  }, [])

  /** ================= 刷新 / 加载更多 ================= */

  const handleRefresh = useCallback(() => {
    queryRef.current.page = 1
    setHasMore(true)
    firstLoadDoneRef.current = false
    fetchList('refresh')
  }, [])

  const handleLoadMore = useCallback(() => {
    // 防止重复请求或首次渲染时误触发
    if (loadingRef.current || !hasMore || refreshing || loadingMore) return
    if (!firstLoadDoneRef.current) return
    // if (allItems.length === 0) return // 首次加载未完成时不触发加载更多

    queryRef.current.page += 1
    fetchList('loadMore')
    console.log('handleLoadMore-------------')
  }, [hasMore, refreshing, loadingMore])

  /** ================= selectedItem 修正 ================= */

  useEffect(() => {
    if (!allItems.length) {
      setSelectedItem(null)
      return
    }
    if (!allItems.find((i) => i.id === selectedItem?.id)) {
      setSelectedItem(allItems[0])
    }
  }, [allItems, selectedItem?.id])

  useEffect(() => {
    fetchList('init')
    // 初次加载时直接加载余额
    userBalanceStore.load(true)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  // 管理轮询：用户登录时启动，登出时停止，使用延迟判断避免刷新时的临时状态
  useEffect(() => {
    // 使用短暂延迟，避免刷新时的临时状态变化
    const timer = setTimeout(() => {
      if (isAuthenticated && user?.id) {
        console.log('用户已登录，启动余额轮询')
        userBalanceStore.startPolling()
      } else {
        console.log('用户未登录，停止余额轮询')
        userBalanceStore.stopPolling()
      }
    }, 100) // 100ms延迟，避免刷新时的快速状态切换

    return () => {
      clearTimeout(timer)
    }
  }, [isAuthenticated, user?.id])

  // 组件卸载时确保轮询停止
  useEffect(() => {
    return () => {
      userBalanceStore.stopPolling()
    }
  }, [])

  useFocusEffect(() => {
    if (isAuthenticated && user?.id) {
      userBalanceStore.load(true)
    }
  })

  /** ================= 快速生成 ================= */

  const handleQuickGen = async () => {
    if (!isAuthenticated) {
      router.push('/auth')
      return
    }
    if (!selectedItem) {
      Toast.show({ title: '请先选择一个模板' })
      return
    }

    // 显示加载状态并刷新余额
    Toast.showLoading()
    try {
      await userBalanceStore.load(true) // 生成前刷新余额

      // 使用最新的余额数据进行检查
      const currentBalance = userBalanceStore.balance
      if (currentBalance < selectedItem.price) {
        Toast.show({ title: '余额不足，请充值' })
        return
      }
    } catch (error) {
      Toast.show({ title: '余额加载失败，请重试' })
      return
    } finally {
      Toast.hideLoading()
    }

    Toast.showModal(
      <ConfirmModal
        content={
          <Text className="text-[14px] font-bold">
            生成将消耗
            <Text className="mx-[4px] text-[20px] text-[#e61e25]">{selectedItem.price}</Text>
          </Text>
        }
        onCancel={Toast.hideModal}
        onConfirm={async () => {
          Toast.hideModal()
          Toast.showLoading()

          try {
            // 先进行乐观更新，扣减余额
            userBalanceStore.deductBalance(selectedItem.price)

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

            if (generationId && user?.id) {
              // 生成成功后强制刷新余额以获取准确数据
              await userBalanceStore.load(true)
              Toast.show({ title: '生成任务开启，请在我的生成中查看' })
            } else {
              // 生成失败，恢复余额
              userBalanceStore.setBalance(userBalanceStore.balance + selectedItem.price)
              Toast.show({ title: error?.message || '生成失败' })
            }
          } catch (error) {
            // 异常情况下恢复余额
            userBalanceStore.setBalance(userBalanceStore.balance + selectedItem.price)
            Toast.show({ title: '网络异常，请重试' })
          } finally {
            Toast.hideLoading()
          }
        }}
      />,
    )
  }

  const renderListEmpty = () => {
    if (activeTab === 'like' && !isAuthenticated) {
      return (
        <Block className="mt-[40px] items-center justify-center gap-[16px] py-[60px]">
          <Block className="size-[80px] items-center justify-center rounded-full border-4 border-white/20 bg-white/10">
            <Ionicons color="rgba(255,255,255,0.6)" name="heart-outline" size={40} />
          </Block>
          <Text className="text-[16px] font-bold text-white/80">查看您收藏的模板</Text>
          <Text className="text-[12px] text-white/50">登录后即可查看和管理收藏</Text>
          <Block
            className="mt-[12px] flex-row items-center gap-[8px] border-[3px] border-white bg-accent px-[32px] py-[12px] shadow-[4px_4px_0px_rgba(255,255,255,0.2)]"
            style={{ transform: [{ skewX: '-6deg' }] }}
            onClick={() => router.push('/auth')}
          >
            <Ionicons color="black" name="flash" size={16} style={{ transform: [{ skewX: '6deg' }] }} />
            <Text className="font-900 text-[14px] text-black" style={{ transform: [{ skewX: '6deg' }] }}>
              立即登录
            </Text>
          </Block>
        </Block>
      )
    } else {
      return <ListEmpty />
    }
  }

  // 缓存渲染函数以提升性能
  const renderItem = useCallback(
    ({ item }: { item: MediaItem }) => (
      <GridItem
        isSelected={selectedItem?.id === item.id}
        item={item}
        itemWidth={ITEM_WIDTH}
        onSelect={() => setSelectedItem(item)}
      />
    ),
    [selectedItem?.id],
  )

  const keyExtractor = useCallback((item: MediaItem) => item.id, [])

  /** ================= UI ================= */
  return (
    <Block className="flex-1 bg-black px-[12px]">
      <BannerSection />

      <HeroCircle onOpenSearch={() => setIsSearchOpen(true)} onQuickGen={handleQuickGen} selectedItem={selectedItem} />

      <FilterSection
        activeTab={activeTab}
        onChange={(tab) => {
          setActiveTab(tab)
          changeTab(tab)
        }}
      />

      <FlashList
        contentContainerStyle={{ paddingBottom: 200, marginTop: 12 }}
        ListFooterComponent={
          loadingMore ? (
            <Block className="items-center py-[20px]">
              <ActivityIndicator color="#FFE500" />
            </Block>
          ) : null
        }
        numColumns={3}
        onEndReached={handleLoadMore}
        drawDistance={1200}
        onEndReachedThreshold={0.3}
        refreshControl={<RefreshControl colors={['#FFE500']} refreshing={refreshing} onRefresh={handleRefresh} />}
        renderItem={renderItem}
        keyExtractor={keyExtractor}
        ListEmptyComponent={renderListEmpty}
        showsVerticalScrollIndicator={false}
        data={allItems}
        // @ts-ignore
        estimatedItemSize={ITEM_WIDTH}
      />

      <SearchOverlay isOpen={isSearchOpen} onClose={() => setIsSearchOpen(false)} onSearch={handleSearch} />
    </Block>
  )
})

type SearchOverlayProps = {
  isOpen: boolean
  searchText?: string
  onChange?: (v: string) => void
  onClose: () => void
  onSearch: (v: string) => void
}
const SearchOverlay = memo<SearchOverlayProps>(function SearchOverlay({ isOpen, onChange, onClose, onSearch }) {
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
  const [searchText, setSearchText] = useState('')

  const handleTextChange = useCallback(
    (text: string) => {
      setSearchText(text)
      onChange?.(text)

      if (timerRef.current) {
        clearTimeout(timerRef.current)
      }

      // 增加防抖时间到500ms，减少频繁搜索
      timerRef.current = setTimeout(() => {
        onSearch(text)
      }, 500)
    },
    [onChange, onSearch],
  )

  const handleClose = useCallback(() => {
    setSearchText('')
    onSearch('')
    onClose?.()
  }, [onClose, onSearch])

  if (!isOpen) return null
  return (
    <Block className="absolute inset-x-0 top-0 z-50 mt-[24px] flex-row items-center gap-[8px] px-[20px]">
      <Block
        className="flex-1 flex-row items-center border-[3px] border-black bg-white px-[12px] shadow-[4px_4px_0px_#000]"
        style={{ height: 48, transform: [{ skewX: '-6deg' }] }}
      >
        <Ionicons color="black" name="search" size={20} style={{ marginRight: 8 }} />
        <TextInput
          autoFocus
          onChangeText={handleTextChange}
          placeholder="搜索作品 / 用户..."
          placeholderTextColor="#9CA3AF"
          style={{
            flex: 1,
            fontSize: 14,
            fontWeight: 'bold',
            color: 'black',
          }}
          value={searchText}
        />
      </Block>
      <Block
        className="items-center justify-center border-[3px] border-black bg-accent shadow-[4px_4px_0px_#000]"
        onClick={handleClose}
        style={{ width: 48, height: 48, transform: [{ skewX: '-6deg' }] }}
      >
        <Ionicons color="black" name="close" size={24} style={{ transform: [{ skewX: '6deg' }] }} />
      </Block>
    </Block>
  )
})

type GooActionsProps = {
  gooPoints: number
  onAddGoo: () => void
  onOpenSearch: () => void
}
const GooActions = observer<GooActionsProps>(function GooActions({ gooPoints, onAddGoo, onOpenSearch }) {
  const { isPolling } = userBalanceStore
  const isDev = __DEV__
  const isAuthenticated = userStore.isAuthenticated
  return (
    <Block>
      <Block className="mt-[12px] flex-row items-center gap-[8px]">
        {!!isAuthenticated && (
          <Block
            className="flex-row items-center gap-[4px] rounded-full border-[3px] border-white bg-black px-[12px] py-[8px] shadow-[3px_3px_0px_rgba(0,0,0,0.5)]"
            onClick={onAddGoo}
          >
            <Text className="text-[12px] font-black text-accent">{gooPoints}</Text>
            <Ionicons color="#FFE500" name="add" size={12} style={{ fontWeight: 'bold' }} />
            {/* 开发模式下显示轮询状态 */}
            {isDev && isPolling && <Block className="ml-[4px] size-[6px] rounded-full bg-green-500" />}
          </Block>
        )}

        <Block
          className="size-[48px] items-center justify-center rounded-full border-[3px] border-black bg-white shadow-[4px_4px_0px_#000]"
          onClick={onOpenSearch}
        >
          <Ionicons color="black" name="search" size={22} />
        </Block>
      </Block>
    </Block>
  )
})

type HeroCircleProps = {
  selectedItem: MediaItem | null
  onQuickGen: () => void
  onOpenSearch: () => void
}
const HeroCircle = observer<HeroCircleProps>(function HeroCircle({ selectedItem, onQuickGen, onOpenSearch }) {
  const isAuthenticated = userStore.isAuthenticated
  const { balance } = userBalanceStore
  const existItem = !!selectedItem?.url
  return (
    <Block className="relative z-10 items-center">
      <Block className="relative mx-[12px] flex-row justify-between">
        <Block className="flex-1">
          <Block className="relative z-10 mt-[20px] flex size-[224px] rounded-full border-4 border-black shadow-deep-black">
            {existItem && (
              <Block className="relative size-full overflow-hidden rounded-full">
                <VideoBox style={{ height: 216, width: 216, borderRadius: 108 }} url={selectedItem.url} />
              </Block>
            )}

            {!existItem && (
              <Block className="relative size-full overflow-hidden rounded-full bg-transparent">
                <Text className="text-[14px] font-bold text-white/60">加载中...</Text>
              </Block>
            )}

            <Block className="pointer-events-none absolute inset-0 rounded-full border-2 border-black/10" />

            <Block className="absolute bottom-[24px] left-[8px] z-20 max-w-[100px] bg-black px-[12px] py-[4px] shadow-small-accent">
              <Text className="font-900 -skew-x-12 text-[10px] text-white" ellipsizeMode="tail" numberOfLines={1}>
                {selectedItem?.title}
              </Text>
            </Block>

            <Block
              className="absolute bottom-[16px] right-0 z-30 -skew-x-6 flex-row items-center gap-[4px] border-[3px] border-black bg-accent px-[16px] py-[6px] shadow-medium-black"
              onClick={onQuickGen}
            >
              <Ionicons color="black" name="flash" size={14} />
              <Text className="font-900 text-[12px] text-black">GET 同款</Text>
            </Block>
          </Block>
        </Block>
        <GooActions
          gooPoints={balance}
          onAddGoo={() => {
            if (!isAuthenticated) {
              router.push('/auth')
            } else {
              router.push('/pointList')
            }
          }}
          onOpenSearch={onOpenSearch}
        />
      </Block>
    </Block>
  )
})

type FilterSectionProps = {
  activeTab: ActiveTab
  onChange: (t: ActiveTab) => void
}
const FilterSection = memo<FilterSectionProps>(function FilterSection({ activeTab, onChange }) {
  const tabs = useMemo(
    () => [
      { label: '最热', state: '' as const },
      { label: '最新', state: 'new' as const },
      { label: '喜欢', state: 'like' as const },
    ],
    [],
  )

  return (
    <Block className="mt-[12px] flex-row items-end justify-between">
      <Block className="flex-row gap-[8px]">
        {tabs.map(({ label, state }) => {
          const isActive = activeTab === state
          return (
            <Block
              className={`border-2 border-black px-[16px] py-[4px] ${isActive ? 'bg-accent' : 'bg-white'}`}
              key={state}
              onClick={() => onChange(state)}
              style={{
                transform: [{ skewX: '-6deg' }],
              }}
            >
              <Text className={`text-[10px] font-[900] ${isActive ? 'text-black' : 'text-gray-500'}`}>{label}</Text>
            </Block>
          )
        })}
      </Block>
    </Block>
  )
})

type GridItemProps = {
  item: MediaItem
  isSelected: boolean
  itemWidth: number
  onSelect: () => void
}

// 优化GridItem组件，减少不必要的重渲染
const GridItem = memo<GridItemProps>(
  function GridItem({ item, isSelected, itemWidth, onSelect }) {
    // console.log('item-------------', item);

    return (
      <Block className="relative mb-[12px]" onClick={onSelect}>
        <Block
          className={`relative overflow-hidden border-2 ${isSelected ? 'border-accent' : 'border-black'}`}
          style={{
            transform: [{ skewX: '-6deg' }],
            height: itemWidth,
            width: itemWidth,
          }}
        >
          <VideoBox style={{ height: itemWidth, width: itemWidth }} url={item.url} />

          {isSelected && <Block className="absolute inset-0 border-[3px] border-accent" />}

          <Block
            className={cn(
              'absolute left-[0px] top-[0px] z-[20] border-b-[2px] border-r-[2px] border-black bg-black px-[6px] py-[2px]',
              {
                'bg-accent': isSelected,
              },
            )}
          >
            <Text
              className={cn('font-900 text-[8px] text-white', {
                'text-black': isSelected,
              })}
            >
              {item.title}
            </Text>
          </Block>

          <Block
            className="absolute inset-x-0 bottom-0 z-20 items-end justify-between p-[4px] pt-[16px]"
            style={{ transform: [{ skewX: '6deg' }] }}
          >
            <LinearGradient
              colors={['rgba(0,0,0,0.8)', 'transparent']}
              end={{ x: 0, y: 0 }}
              start={{ x: 0, y: 1 }}
              style={{
                position: 'absolute',
                left: 0,
                right: 0,
                top: 0,
                bottom: 0,
              }}
            />

            <Block className="w-full flex-1 flex-row items-center justify-between px-[4px]">
              <Block className="">
                <Text className="font-900 max-w-[40px] -skew-x-6 text-[7px] text-white" numberOfLines={1}>
                  {item.authorName || '未知作者'}
                </Text>
              </Block>
              <Block className="-skew-x-6 flex-row items-center gap-[2px]">
                <Ionicons color="#FF0000" name="heart" size={10} />
                <Text className="font-900 text-[8px] text-white">{item.likeCount}</Text>
              </Block>
            </Block>
          </Block>
        </Block>
      </Block>
    )
  },
  (prevProps, nextProps) => {
    // 自定义比较函数，只在关键属性变化时才重渲染
    return (
      prevProps.item.id === nextProps.item.id &&
      prevProps.isSelected === nextProps.isSelected &&
      prevProps.itemWidth === nextProps.itemWidth &&
      prevProps.item.likeCount === nextProps.item.likeCount
    )
  },
)

export default Index
