import { FontAwesome, Fontisto, Ionicons } from '@expo/vector-icons'
import { FlashList } from '@shopify/flash-list'
import { useFocusEffect, useRouter } from 'expo-router'
import { observer } from 'mobx-react-lite'
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { ActivityIndicator, RefreshControl } from 'react-native'
import { useAnimatedStyle } from 'react-native-reanimated'
import { useSafeAreaInsets } from 'react-native-safe-area-context'

import { imgPicker } from '@/@share/apis/imgPicker'
import { Block, ConfirmModal, Img, Input, ListEmpty, Text, Toast, VideoBox } from '@/@share/components'
import BannerSection from '@/components/BannerSection'
import { useTemplateActions } from '@/hooks/actions/use-template-actions'
import { useTemplates } from '@/hooks/data/use-templates'
import { userBalanceStore, userStore } from '@/stores'
import { screenHeight, screenWidth, uploadFile } from '@/utils'

const CATEGORY_ID = process.env.EXPO_PUBLIC_GENERATE_GROUP_ID

type Template = {
  id: string
  name: string
  image: string
  videoUrl: string
  type: 'video'
  price?: number
  data?: any
}
/** =========================
 * Entry page
 * ========================= */
const Generate = observer(function Generate() {
  const router = useRouter()

  const { user, isAuthenticated } = userStore

  const [prompt, setPrompt] = useState(``)
  const [selectedTemplateId, setSelectedTemplateId] = useState('')
  const [meImg, setMeImg] = useState({ uri: '', url: '' })
  const [friendImg, setFriendImg] = useState({ uri: '', url: '' })

  const templates = useTemplates()
  const { runTemplate } = useTemplateActions()

  useFocusEffect(() => {
    if (!isAuthenticated) {
      router.replace('/')
      router.push('/auth')
    }
  })

  useEffect(() => {
    templates.execute({ categoryId: CATEGORY_ID, page: 1, limit: 12, sortBy: 'createdAt', sortOrder: 'desc' })
  }, [])

  const displayTemplates = useMemo(() => {
    const regular = templates.data?.templates || []
    const all = regular
    return all.map((t: any): Template => {
      return {
        id: t.id,
        name: t.title,
        image: t.coverImageUrl,
        videoUrl: t.previewUrl,
        type: 'video' as const,
        price: t.price,
        data: {
          startNodes: t?.formSchema?.startNodes || [],
        },
      }
    })
  }, [templates.data])

  const selectedTemplate = useMemo(() => {
    return displayTemplates.find((t) => t.id === selectedTemplateId)
  }, [displayTemplates, selectedTemplateId])

  useEffect(() => {
    if (displayTemplates.length > 0 && !selectedTemplateId) {
      setSelectedTemplateId(displayTemplates[0].id)
    }
  }, [displayTemplates, selectedTemplateId])

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

  const handleGenerate = async () => {
    if (!selectedTemplate) return

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

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

      // 使用最新的余额数据进行检查
      const currentBalance = userBalanceStore.balance
      if (currentBalance < selectedTemplate?.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]">{selectedTemplate.price} </Text>
          </Text>
        }
        onCancel={Toast.hideModal}
        onConfirm={handleConfirmGenerate}
      />,
    )
  }

  const handleConfirmGenerate = async () => {
    Toast.hideModal()
    Toast.showLoading()

    console.log('meImg.url-------', meImg)

    const data = {} as any
    const startNodes = selectedTemplate?.data?.startNodes || []

    startNodes.map((node: any) => {
      if (node.type === 'text') {
        data[node.id] = prompt
      } else if (node.type === 'image') {
        data[node.id] = meImg.url
      }
    })
    console.log('data==========', data)

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

      const { generationId, error } = await runTemplate({
        templateId: selectedTemplate?.id as string,
        data: 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 pickImage = useCallback(async (target: 'me' | 'friend') => {
    const assetList = (await imgPicker({ maxImages: 1, resultType: 'asset' })) as string[]

    const result = assetList[0] as any
    if (!result) return

    const uri = result?.uri
    if (target === 'me') setMeImg({ uri, url: '' })
    else setFriendImg({ uri, url: '' })

    const url = await uploadFile({
      uri: result.uri,
      mimeType: result.mimeType,
      fileName: result.fileName,
    })

    console.log('handlePick------------', url)

    // console.log('pickImage---------url:', url, 'error:', error)

    if (target === 'me') {
      setMeImg((state) => {
        return { uri: state.uri, url }
      })
    } else {
      setFriendImg((state) => {
        return { uri: state.uri, url }
      })
    }
  }, [])

  const handleRandom = useCallback(() => {
    if (displayTemplates.length === 0) return
    const random = displayTemplates[Math.floor(Math.random() * displayTemplates.length)]
    setSelectedTemplateId(random.id)
  }, [displayTemplates])

  const handleSelectTemplate = useCallback((t: Template) => {
    setSelectedTemplateId(t.id)
  }, [])

  const onPickMe = useCallback(() => pickImage('me'), [pickImage])
  const onPickFriend = useCallback(() => pickImage('friend'), [pickImage])

  const isLoading = templates.loading
  const isLoadingMore = templates.loadingMore
  const hasError = templates.error

  const handleRetry = useCallback(() => {
    templates.refetch({ categoryId: CATEGORY_ID, page: 1, limit: 20, sortBy: 'createdAt', sortOrder: 'desc' })
  }, [templates])

  const [refreshing, setRefreshing] = useState(false)
  const onRefresh = useCallback(async () => {
    setRefreshing(true)
    try {
      await templates.refetch({ categoryId: CATEGORY_ID, page: 1, limit: 20, sortBy: 'createdAt', sortOrder: 'desc' })
    } finally {
      setRefreshing(false)
    }
  }, [templates])

  const onLoadMore = useCallback(() => {
    templates.loadMore({ categoryId: CATEGORY_ID, limit: 20, sortBy: 'createdAt', sortOrder: 'desc' })
  }, [templates])

  const itemWidth = useMemo(() => {
    return Math.floor((screenWidth - 24 - 12 * 2) / 3)
  }, [])

  const renderItem = useCallback(
    ({ item }: { item: Template }) => {
      const isSelected = selectedTemplateId === item.id
      return (
        <TemplateItem
          isSelected={isSelected}
          item={item}
          key={item?.id}
          itemWidth={itemWidth}
          onSelect={() => handleSelectTemplate(item)}
        />
      )
    },
    [selectedTemplateId, itemWidth, handleSelectTemplate],
  )

  const ListHeader = useMemo(() => {
    const startNodes = selectedTemplate?.data?.startNodes || []
    const textCount = startNodes.filter((node: any) => node?.type === 'text').length

    return (
      <Block className="">
        <Header onSearch={handleSearch} />
        <Block className="px-12px relative z-10">
          <UploadSection
            friendImg={friendImg?.uri}
            meImg={meImg?.uri}
            onPickFriend={onPickFriend}
            onPickMe={onPickMe}
            selectedTemplate={selectedTemplate}
          />
          {!!textCount && <PromptSection prompt={prompt} onChangePrompt={setPrompt} />}
          <TemplateSectionHeader onRandom={handleRandom} />
        </Block>
      </Block>
    )
  }, [handleSearch, friendImg, meImg, onPickFriend, onPickMe, prompt, handleRandom, selectedTemplate])

  const ListFooter = useMemo(() => {
    if (isLoadingMore) {
      return (
        <Block className="items-center justify-center py-[20px]">
          <ActivityIndicator color="#FFE500" size="small" />
        </Block>
      )
    }
    return <Block className="h-[200px] w-full" />
  }, [isLoadingMore])

  return (
    <Block className="relative flex-1 overflow-visible bg-black">
      <BannerSection />

      <FlashList
        contentContainerStyle={{ paddingHorizontal: 12, paddingBottom: 200 }}
        data={displayTemplates}
        drawDistance={screenHeight}
        // @ts-ignore
        estimatedItemSize={itemWidth}
        extraData={selectedTemplateId}
        keyExtractor={(item) => item.id}
        ListEmptyComponent={<ListEmpty hasError={hasError} handleRetry={handleRetry} />}
        ListFooterComponent={ListFooter}
        ListHeaderComponent={ListHeader}
        numColumns={3}
        renderItem={renderItem}
        showsVerticalScrollIndicator={false}
        refreshControl={
          <RefreshControl colors={['#FFE500']} refreshing={refreshing} tintColor="#fff" onRefresh={onRefresh} />
        }
        onEndReached={onLoadMore}
        onEndReachedThreshold={0.3}
      />

      <GenerateSection selectedTemplate={selectedTemplate} onGenerate={handleGenerate} />
    </Block>
  )
})

export default Generate
/** =========================
 * Small memo components
 * ========================= */

type HeaderProps = { onSearch: () => void }
const Header = memo<HeaderProps>(function Header({ onSearch }) {
  return (
    <Block className="z-20 flex-row items-center justify-between py-[12px]">
      {/* <Block className="-skew-x-12 flex-row items-center gap-[8px] border border-white/20 bg-black px-[12px] py-[4px]">
        <Block className="size-[8px] bg-accent" />
        <Text className="font-700 skew-x-12 text-[12px] tracking-wider text-white">创造终端</Text>
      </Block>

      <Block className="items-center">
        <Text className="font-700 text-[24px] tracking-tighter text-white">GEN_STUDIO</Text>
      </Block> */}

      <Block className="-skew-x-12 flex-row items-center gap-[8px] border border-white/20 bg-black px-[12px] py-[4px] opacity-0">
        <Block className="size-[8px] bg-accent" />
        <Text className="font-700 skew-x-12 text-[12px] tracking-wider text-white">创造终端</Text>
      </Block>
    </Block>
  )
})

type UploadCardProps = {
  variant: 'me' | 'friend'
  img: string
  onPick: () => void
}
const UploadCard = memo<UploadCardProps>(function UploadCard({ variant, img, onPick }) {
  const isMe = variant === 'me'

  return (
    <Block className="flex-1 overflow-hidden border-[3px] border-black bg-white" onClick={onPick}>
      {isMe ? (
        <Block className="absolute left-0 top-0 z-10 border-b-2 border-r-2 border-black bg-accent px-[8px] py-[2px]">
          <Text className="text-[10px] font-[900] text-black">我</Text>
        </Block>
      ) : (
        <Block className="absolute right-0 top-0 z-10 border-b-2 border-l-2 border-white bg-black px-[8px] py-[2px]">
          <Text className="text-[10px] font-[900] text-white">朋友</Text>
        </Block>
      )}

      <Block className="size-full items-center justify-center bg-[#F3F4F6]">
        {img ? (
          <Img className="size-full" contentFit="cover" src={img} />
        ) : (
          <Block className="items-center">
            {isMe ? (
              <Block className="mb-[4px] size-[40px] items-center justify-center rounded-[20px] border-2 border-black bg-white">
                <Text className="font-700 text-[16px] text-black">+</Text>
              </Block>
            ) : (
              <Block className="mb-[4px] size-[40px] items-center justify-center rounded-[20px] bg-black">
                <Text className="font-700 text-[16px] text-white">+</Text>
              </Block>
            )}

            <Text className="font-700 text-[9px] text-black/50">点击上传</Text>
          </Block>
        )}
      </Block>
    </Block>
  )
})

type UploadSectionProps = {
  meImg: string
  friendImg: string
  onPickMe: () => void
  onPickFriend: () => void
  selectedTemplate: Template | undefined
}
const UploadSection = memo<UploadSectionProps>(function UploadSection({
  meImg,
  friendImg,
  onPickMe,
  onPickFriend,
  selectedTemplate,
}) {
  const imageCount = useMemo(() => {
    if (!selectedTemplate) return true
    const startNodes = selectedTemplate?.data?.startNodes || []
    const imageNodeCount = startNodes.filter((node: any) => node?.type === 'image').length
    return imageNodeCount
  }, [selectedTemplate])

  if (imageCount === 0) return null
  return (
    <Block className="z-10 flex h-[160px] w-full flex-row gap-x-[12px]">
      {imageCount >= 1 && <UploadCard img={meImg} variant="me" onPick={onPickMe} />}
      {imageCount >= 2 && <UploadCard img={friendImg} variant="friend" onPick={onPickFriend} />}
    </Block>
  )
})

type PromptSectionProps = {
  prompt: string
  editable?: boolean
  onChangePrompt: (v: string) => void
}
const PromptSection = memo<PromptSectionProps>(function PromptSection({ prompt, onChangePrompt, editable = true }) {
  return (
    <Block className="mt-[24px] -skew-x-6">
      <Block className="mb-[4px] flex-row items-center px-[4px]">
        <Block className="border border-white/20 bg-black px-[8px] py-[2px]">
          <Text className="text-[12px] font-[900] text-accent">提示词</Text>
        </Block>
      </Block>

      <Block className={`border-[3px] border-black bg-white p-[4px]`}>
        <Input
          multiline
          className="w-full bg-transparent p-[8px] text-[14px] leading-[18px] text-black"
          style={{ height: 50 }}
          numberOfLines={2}
          placeholder={editable ? '描述画面细节...' : '请先选择模板'}
          value={prompt}
          editable={editable}
          onChangeText={onChangePrompt}
        />
      </Block>
    </Block>
  )
})

type TemplateItemProps = {
  item: Template
  itemWidth: number
  isSelected: boolean
  onSelect: () => void
}
const TemplateItem = memo<TemplateItemProps>(function TemplateItem({ item, itemWidth, isSelected, onSelect }) {
  return (
    <Block
      key={item?.id}
      className={`relative overflow-hidden border-2 ${isSelected ? 'border-accent' : 'border-black'}`}
      style={{
        transform: [{ skewX: '-6deg' }],
        height: itemWidth,
        width: itemWidth,
        borderWidth: 2,
        marginBottom: 12,
        borderColor: isSelected ? '#FFE500' : '#000000',
      }}
      onClick={onSelect}
    >
      {/* <Img className="size-full" contentFit="cover" src={item.image} /> */}
      <VideoBox style={{ width: itemWidth, height: itemWidth }} url={item.videoUrl} />

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

      <Block className="absolute inset-x-0 bottom-0 items-center bg-black/90 p-[4px]">
        <Text className={`text-[8px] font-[700] ${isSelected ? 'text-accent' : 'text-white'}`}>{item.name}</Text>
      </Block>

      {item.type === 'video' && (
        <Block className="rounded-4px absolute right-[4px] top-[4px] rounded-[4px] border border-white/50 bg-black p-[4px]">
          <Fontisto color="white" name="youtube-play" size={8} />
        </Block>
      )}
    </Block>
  )
})

type TemplateSectionHeaderProps = {
  onRandom: () => void
}
const TemplateSectionHeader = memo<TemplateSectionHeaderProps>(function TemplateSectionHeader({ onRandom }) {
  const style = useAnimatedStyle(() => ({
    transform: [{ skewX: '-6deg' }],
    backgroundColor: '#FFE500',
  }))

  return (
    <Block className="my-[16px]">
      <Block className="flex-row items-center justify-between">
        <Block
          animated
          className="flex-row items-center gap-[8px] border-2 border-black bg-accent px-[12px] py-[4px]"
          style={style}
        >
          <FontAwesome color="black" name="film" size={16} />
          <Text className="text-[10px] font-[900] text-black">视频模版</Text>
        </Block>

        <Block
          className="-skew-x-6 items-center justify-center border-2 border-black bg-white px-[8px] py-[4px]"
          onClick={onRandom}
        >
          <Text className="text-[10px] font-[900] text-black">换一波</Text>
        </Block>
      </Block>
    </Block>
  )
})

type GenerateSectionProps = {
  selectedTemplate: Template | undefined
  onGenerate: () => void
}
const GenerateSection = memo<GenerateSectionProps>(function GenerateSection({ selectedTemplate, onGenerate }) {
  const insets = useSafeAreaInsets()

  if (!selectedTemplate) return null

  const price = selectedTemplate.price || selectedTemplate.data?.price || 0

  return (
    <Block className="absolute inset-x-[16px] bottom-[96px] z-40" style={{ paddingBottom: insets.bottom }}>
      <Block style={{ transform: [{ skewX: '-6deg' }] }}>
        <Block
          className={`relative flex-row items-center justify-between border-[3px] border-black bg-accent py-[8px]`}
          style={{ paddingHorizontal: 24 }}
          onClick={onGenerate}
        >
          {/* 左侧文字 */}
          <Block className="z-10 flex-col">
            <Text className={`text-[24px] text-black`}>立即生成</Text>
            <Text className={`text-[10px] font-bold text-black`}>开始创作</Text>
          </Block>

          {/* 右侧  标签 */}
          <Block className="z-10 flex-row items-center gap-[8px] border-2 border-black bg-black px-[12px] py-[4px]">
            <Ionicons color="#FFE500" name="flash" size={14} />
            <Text className="text-[14px] font-black text-accent">{price}</Text>
          </Block>
        </Block>
      </Block>
    </Block>
  )
})
