import { Ionicons } from '@expo/vector-icons'
import type { GetUserFavoritesResponse } from '@repo/sdk'
import { Block, ConfirmModal, Text, Toast, VideoBox } from '@share/components'
import Img from '@share/components/Img'
import { FlashList } from '@shopify/flash-list'
import { LinearGradient } from 'expo-linear-gradient'
import { router } from 'expo-router'
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 { useAuth } from '@/hooks/core/use-auth'
import { useUserBalance } from '@/hooks/core/use-user-balance'
import { useTemplates } from '@/hooks/data'
import { useFavoriteTemplates } from '@/hooks/data/use-favorite-templates'
import { usePublicTemplates } from '@/hooks/data/use-public-templates'
import { screenWidth } from '@/utils'
import { cn } from '@/utils/cn'

const CATEGORY_ID = process.env.EXPO_PUBLIC_INDEX_GROUP_ID

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

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

export default function Sync() {
  const { user, isAuthenticated } = useAuth()
  const { balance, load: loadBalance } = useUserBalance()
  const { data: templatesData, loading: templatesLoading, execute: loadTemplates } = useTemplates()
  const {
    data: publicTemplatesData,
    loading: publicTemplatesLoading,
    execute: loadPublicTemplates,
  } = usePublicTemplates()
  const { data: favoritesData, loading: favoritesLoading, execute: loadFavorites } = useFavoriteTemplates()
  const { runTemplate } = useTemplateActions()

  const [searchText, setSearchText] = useState('')
  const searchTextRef = useRef('')

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

  const [page, setPage] = useState(1)
  const [hasMore, setHasMore] = useState(true)
  const [refreshing, setRefreshing] = useState(false)
  const [loadingMore, setLoadingMore] = useState(false)
  const [allItems, setAllItems] = useState<MediaItem[]>([])
  const isLoadingRef = useRef(false)

  const onAddGoo = useCallback(() => {
    router.push('/pointList')
  }, [])

  const transformTemplateToMediaItem = useCallback((template: any): MediaItem => {
    const isVideo = template.previewUrl?.includes('.mp4')
    return {
      id: template.id,
      type: (isVideo ? 'video' : 'image') as 'video' | 'image',
      url: isVideo ? template.previewUrl : template.coverImageUrl || template.previewUrl,
      poster: isVideo ? template.coverImageUrl : undefined,
      likeCount: template.likeCount || 0,
      price: template.price || 2, // 默认为 2 Goo
    }
  }, [])

  const galleryItems = useMemo<MediaItem[]>(() => allItems, [allItems])

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

  useEffect(() => {
    if (galleryItems.length > 0 && !selectedItem) {
      setSelectedItem(galleryItems[0])
    }
  }, [galleryItems, selectedItem])

  useEffect(() => {
    if (isAuthenticated && user?.id) {
      loadBalance()
    }
  }, [isAuthenticated, user?.id])

  // Tab 切换时重置并加载数据

  const initialLoad = async () => {
    if (isLoadingRef.current) return
    isLoadingRef.current = true
    setRefreshing(true)
    try {
      let newItems: MediaItem[] = []
      const limit = 20

      if (activeTab === 'like') {
        if (!isAuthenticated) {
          setHasMore(false)
          return
        }
        const { data, error } = await loadFavorites({ limit, page: 1 })
        if (error || !data?.favorites) {
          setHasMore(false)
          return
        }
        newItems = data.favorites
          .filter((fav: GetUserFavoritesResponse['favorites'][number]) => fav.template && !fav.template.isDeleted)
          .map((fav: GetUserFavoritesResponse['favorites'][number]) => transformTemplateToMediaItem(fav.template!))
      } else if (activeTab === 'new') {
        const { data, error } = await loadTemplates({
          limit,
          page: 1,
          sortBy: 'createdAt',
          sortOrder: 'desc',
          search: searchTextRef.current,
        })
        if (error || !data?.templates) {
          setHasMore(false)
          return
        }
        newItems = data.templates.map(transformTemplateToMediaItem)
      } else {
        const { data, error } = await loadTemplates({
          limit,
          page: 1,
          sortBy: 'likeCount',
          sortOrder: 'desc',
          search: searchTextRef.current,
        })
        if (error || !data?.templates) {
          setHasMore(false)
          return
        }
        newItems = data.templates.map(transformTemplateToMediaItem)
      }

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

      setAllItems(newItems)
    } catch (error) {
      console.error('Failed to load data:', error)
      setHasMore(false)
    } finally {
      isLoadingRef.current = false
      setRefreshing(false)
    }
  }

  useEffect(() => {
    setPage(1)
    setHasMore(true)
    setAllItems([])

    initialLoad()
  }, [activeTab, isAuthenticated])

  const loadData = useCallback(
    async (pageNum: number, isRefresh: boolean = false) => {
      if (!isRefresh && !hasMore) return
      if (loadingMore || refreshing || isLoadingRef.current) return

      isLoadingRef.current = true

      if (isRefresh) {
        setRefreshing(true)
      } else {
        setLoadingMore(true)
      }

      try {
        let newItems: MediaItem[] = []
        const limit = 21

        if (activeTab === 'like') {
          if (!isAuthenticated) {
            setHasMore(false)
            return
          }
          const { data, error } = await loadFavorites({ limit, page: pageNum })
          if (error || !data?.favorites) {
            setHasMore(false)
            return
          }
          newItems = data.favorites
            .filter((fav: GetUserFavoritesResponse['favorites'][number]) => fav.template && !fav.template.isDeleted)
            .map((fav: GetUserFavoritesResponse['favorites'][number]) => transformTemplateToMediaItem(fav.template!))
        } else if (activeTab === 'new') {
          if (!isAuthenticated) {
            setHasMore(false)
            return
          }
          const { data, error } = await loadTemplates({
            limit,
            page: pageNum,
            sortBy: 'createdAt',
            categoryId: CATEGORY_ID,
            sortOrder: 'desc',
          })
          if (error || !data?.templates) {
            setHasMore(false)
            return
          }
          newItems = data.templates.map(transformTemplateToMediaItem)
        } else {
          if (!isAuthenticated) {
            setHasMore(false)
            return
          }
          const { data, error } = await loadTemplates({
            limit,
            page: pageNum,
            sortBy: 'likeCount',
            categoryId: CATEGORY_ID,
            sortOrder: 'desc',
          })
          if (error || !data?.templates) {
            setHasMore(false)
            return
          }
          newItems = data.templates.map(transformTemplateToMediaItem)
        }

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

        if (isRefresh) {
          setAllItems(newItems)
        } else {
          setAllItems((prev) => [...prev, ...newItems])
        }
      } catch (error) {
        console.error('Failed to load data:', error)
        setHasMore(false)
      } finally {
        isLoadingRef.current = false
        setRefreshing(false)
        setLoadingMore(false)
      }
    },
    [
      activeTab,
      isAuthenticated,
      hasMore,
      loadingMore,
      refreshing,
      loadTemplates,
      loadPublicTemplates,
      loadFavorites,
      transformTemplateToMediaItem,
    ],
  )

  const handleRefresh = useCallback(() => {
    setPage(1)
    setHasMore(true)
    loadData(1, true)
  }, [loadData])

  const handleLoadMore = useCallback(() => {
    if (!hasMore || loadingMore || refreshing || isLoadingRef.current) return
    const nextPage = page + 1
    setPage(nextPage)
    loadData(nextPage, false)
  }, [page, hasMore, loadingMore, refreshing, loadData])

  const handleQuickGen = useCallback(async () => {
    if (!isAuthenticated) {
      Toast.show({ title: '请先登录' })
      return
    }

    if (!selectedItem) {
      Toast.show({ title: '请先选择一个模板' })
      return
    }

    const cost = selectedItem.price

    if (balance < cost) {
      Toast.show({ title: '余额不足，请充值' })
      return
    }

    Toast.showModal(
      <ConfirmModal
        content={
          <Text className="text-[14px] font-bold leading-relaxed text-gray-800">
            生成同款风格将消耗 <Text className="mx-[4px] text-[20px] font-black italic text-[#e61e25]">{cost} Goo</Text>{' '}
            算力。
          </Text>
        }
        onCancel={() => Toast.hideModal()}
        onConfirm={async () => {
          Toast.hideModal()
          // 要传 扣费返回的凭证
          const { generationId, error } = await runTemplate({
            templateId: selectedItem.id,
            data: {},
            originalUrl: selectedItem.url,
          })

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

          Toast.show({ title: '正在生成中，请在同步页面查看' })
          if (user?.id) loadBalance()
        }}
      />,
      {},
    )
  }, [isAuthenticated, balance, selectedItem, runTemplate, user?.id, loadBalance])

  const openSearch = useCallback(() => setIsSearchOpen(true), [])
  const closeSearch = useCallback(() => {
    setIsSearchOpen(false)
  }, [])
  const handleSearch = useCallback((text: string) => {
    console.log('Search for:', text)
    // Implement your search logic here
    setSearchText(text)
    searchTextRef.current = text
    initialLoad()
  }, [])

  const itemWidth = Math.floor((screenWidth - 24 - 12 * 2) / 3)
  const renderGridItem = useCallback(
    ({ item }: { item: MediaItem }) => {
      const isSelected = selectedItem?.id === item.id
      return (
        <GridItem isSelected={isSelected} item={item} itemWidth={itemWidth} onSelect={() => setSelectedItem(item)} />
      )
    },
    [selectedItem?.id],
  )

  const renderListFooter = useCallback(() => {
    if (!loadingMore) return null
    return (
      <Block className="items-center py-[20px]">
        <ActivityIndicator color="#FFE500" size="small" />
      </Block>
    )
  }, [loadingMore])

  const renderListEmpty = useCallback(() => {
    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] italic text-black" style={{ transform: [{ skewX: '6deg' }] }}>
              立即登录
            </Text>
          </Block>
        </Block>
      )
    }
    return (
      <Block className="mt-[12px] items-center justify-center py-[40px]">
        <Text className="text-[14px] font-bold text-white/60">暂无内容</Text>
      </Block>
    )
  }, [activeTab, isAuthenticated])

  return (
    <Block className="relative flex-1 flex-col overflow-visible bg-black px-[12px]">
      <BannerSection />

      <HeroCircle
        rightSlot={<GooActions gooPoints={balance} onAddGoo={onAddGoo} onOpenSearch={openSearch} />}
        selectedItem={selectedItem}
        onQuickGen={handleQuickGen}
      />

      <FilterSection activeTab={activeTab} onChange={setActiveTab} />

      <FlashList
        contentContainerStyle={{ marginTop: 12, paddingBottom: 200 }}
        data={galleryItems}
        drawDistance={1200}
        // @ts-ignore
        estimatedItemSize={itemWidth}
        extraData={selectedItem?.id}
        keyExtractor={(item) => item.id}
        ListEmptyComponent={renderListEmpty}
        ListFooterComponent={renderListFooter}
        numColumns={3}
        renderItem={renderGridItem}
        showsVerticalScrollIndicator={false}
        refreshControl={
          <RefreshControl colors={['#FFE500']} refreshing={refreshing} tintColor="#FFE500" onRefresh={handleRefresh} />
        }
        onEndReached={handleLoadMore}
        onEndReachedThreshold={0.5}
      />

      <SearchOverlay isOpen={isSearchOpen} onClose={closeSearch} 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 = (text: string) => {
    setSearchText(text)
    onChange && onChange(text)

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

    timerRef.current = setTimeout(() => {
      onSearch(text)
    }, 2000)
  }

  useEffect(() => {
    // 删除定时器
    return () => {
      if (timerRef.current) {
        clearTimeout(timerRef.current)
      }
    }
  }, [])

  const handleClose = () => {
    setSearchText('')
    onSearch('')
    onClose && onClose()
  }

  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
          placeholder="搜索作品 / 用户..."
          placeholderTextColor="#9CA3AF"
          value={searchText}
          style={{
            flex: 1,
            fontSize: 14,
            fontWeight: 'bold',
            color: 'black',
          }}
          onChangeText={handleTextChange}
        />
      </Block>
      <Block
        className="items-center justify-center border-[3px] border-black bg-accent shadow-[4px_4px_0px_#000]"
        style={{ width: 48, height: 48, transform: [{ skewX: '-6deg' }] }}
        onClick={handleClose}
      >
        <Ionicons color="black" name="close" size={24} style={{ transform: [{ skewX: '6deg' }] }} />
      </Block>
    </Block>
  )
})

type GooActionsProps = {
  gooPoints: number
  onAddGoo: () => void
  onOpenSearch: () => void
}
const GooActions = memo<GooActionsProps>(function GooActions({ gooPoints, onAddGoo, onOpenSearch }) {
  return (
    <Block>
      <Block className="mt-[12px] flex-row items-center gap-[8px]">
        <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 italic text-accent">{gooPoints} Goo</Text>
          <Ionicons color="#FFE500" name="add" size={12} style={{ fontWeight: 'bold' }} />
        </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
  rightSlot: React.ReactNode
}
const HeroCircle = memo<HeroCircleProps>(function HeroCircle({ selectedItem, onQuickGen, rightSlot }) {
  if (!selectedItem) {
    return (
      <Block className="relative z-10 mt-[12px] items-center justify-between px-[12px]">
        <Block className="relative flex-row justify-between">
          <Block className="relative z-10 mt-[20px] size-[224px] items-center justify-center rounded-full border-4 border-black bg-white/20 shadow-deep-black">
            <Text className="text-[14px] font-bold text-white/60">加载中...</Text>
          </Block>
          {rightSlot}
        </Block>
      </Block>
    )
  }

  return (
    <Block className="relative z-10 items-center justify-between">
      <Block className="relative mx-[12px] flex-row justify-between">
        <Block className="relative z-10 mt-[20px] size-[224px] rounded-full border-4 border-black bg-white shadow-deep-black">
          <Block className="relative size-full overflow-hidden rounded-full bg-black">
            {selectedItem.type === 'video' ? (
              <VideoBox style={{ height: 216, width: 216, borderRadius: 108 }} url={selectedItem.url} />
            ) : (
              <Img className="size-full" src={selectedItem.url} />
            )}

            <Block className="absolute inset-0">
              <LinearGradient
                colors={['rgba(255,255,255,0.3)', 'transparent']}
                end={{ x: 1, y: 1 }}
                start={{ x: 0, y: 0 }}
                style={{
                  position: 'absolute',
                  left: 0,
                  right: 0,
                  top: 0,
                  bottom: 0,
                  borderRadius: 9999,
                }}
              />
            </Block>
          </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] italic text-white" ellipsizeMode="tail" numberOfLines={1}>
              {selectedItem?.id}
            </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] italic text-black">GET 同款</Text>
          </Block>
        </Block>

        {rightSlot}
      </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
              key={state}
              className={`border-2 border-black px-[16px] py-[4px] ${isActive ? 'bg-accent' : 'bg-white'}`}
              style={{
                transform: [{ skewX: '-6deg' }],
              }}
              onClick={() => onChange(state)}
            >
              <Text className={`text-[10px] font-[900] italic ${isActive ? 'text-black' : 'text-gray-500'}`}>
                {label}
              </Text>
            </Block>
          )
        })}
      </Block>
    </Block>
  )
})

type GridItemProps = {
  item: MediaItem
  isSelected: boolean
  itemWidth: number
  onSelect: () => void
}
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.id}
          </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] italic text-white" numberOfLines={1}>
                {item.id}
              </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] italic text-white">{item.likeCount}</Text>
            </Block>
          </Block>
        </Block>
      </Block>
    </Block>
  )
})
