import Feather from '@expo/vector-icons/Feather'
import { FlashList } from '@shopify/flash-list'
import { useQuery } from '@tanstack/react-query'
import { type ErrorBoundaryProps, Link } from 'expo-router'
import { useCallback } from 'react'
import { ActivityIndicator, Keyboard, Pressable } from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
import EmojiText from 'src/components/common/EmojiText'
import { ErrorState } from 'src/components/common/ErrorState'
import UserAvatar from 'src/components/common/UserAvatar'
import { useScreenMenu, useSearchQuery } from 'src/components/menu'
import { ICON } from 'src/lib/icons'
import { chatQueries } from 'src/lib/queries/chats'
import { searchQueries } from 'src/lib/queries/search'
import { useActiveProfile, useAuth } from 'src/state/AuthProvider'
import {
  formatTimestampMonthYear,
  getDomain,
  postCountLabel,
  prettyCount,
} from 'src/utils'
import { Text, useTheme, View, XStack, YStack } from 'tamagui'

export function ErrorBoundary({ error, retry }: ErrorBoundaryProps) {
  return <ErrorState message={error.message} onRetry={retry} />
}

export default function SearchScreen() {
  const [query, setQuery] = useSearchQuery()
  const { profile } = useActiveProfile()
  const acct = profile?.acct ?? ''
  const { user: account } = useAuth()
  // Phase C §4.6 of the Mastodon follow-up plan: Mastodon has no
  // `compose/mutuals` equivalent. The new-message flow falls back to the
  // user-search results only — the user types a webfinger/handle/url and
  // taps a result to start a thread. The Pixelfed branch keeps the prior
  // "show mutuals when query is empty" affordance.
  const isMastodon = account?.type === 'mastodon'
  const theme = useTheme()

  useScreenMenu({
    intents: [
      {
        kind: 'search',
        placeholder: 'Search by username, webfinger or url',
        value: query,
        onChangeText: setQuery,
        mode: 'inline',
        keepVisibleOnKeyboard: true,
      },
    ],
  })

  const { data: mutuals = [] } = useQuery({
    ...chatQueries.composeMutuals(),
    select: (data: any) => data?.data || [],
    retry: false,
    staleTime: 5 * 60 * 1000,
    // Pixelfed-only — `composeMutuals` calls `api/v1.1/direct/compose/mutuals`
    // which is `pixelfedActiveContext()`-asserted. Disabling on Mastodon
    // keeps the screen quiet rather than throwing on first mount.
    enabled: !isMastodon,
  })

  const {
    data = [],
    isLoading,
    isError,
    error,
    isFetching,
  } = useQuery({
    ...searchQueries.results(query),
    select: (res: any) =>
      res.filter((r: any) => r._type === 'account' && r.acct !== acct),
    keepPreviousData: true,
  } as any)

  const dataSource =
    isLoading || (query?.length > 0 && (data as any).length) ? data : mutuals

  const renderEmptyResults = useCallback(() => {
    if (!query || isFetching) return null
    return (
      <View flexGrow={1} justifyContent="center" alignItems="center" py="$5">
        <YStack justifyContent="center" alignItems="center" gap="$5">
          <Feather name="alert-circle" size={ICON.empty} />
          <Text fontSize="$9">No results found</Text>
        </YStack>
      </View>
    )
  }, [query, isFetching])

  const renderItem = useCallback(
    ({ item }: { item: any }) => (
      <View p="$3" bg={theme.backgroundSecondary.val}>
        <Link href={`/chats/conversation/${item.id}`} asChild>
          <Pressable>
            <XStack alignItems="center" gap="$3">
              <UserAvatar url={item.avatar} size="md" />
              <YStack flexGrow={1} gap={4}>
                <XStack w="100%" alignItems="center" flexWrap="wrap" overflow="hidden">
                  <EmojiText
                    variant="display"
                    text={item.display_name?.trim() || item.username}
                    emojis={item.emojis}
                    numberOfLines={1}
                  />
                  {!item.local && (
                    <Text fontSize="$6" color={theme.colorTertiary.val}>
                      {' '}
                      @{getDomain(item.url)}
                    </Text>
                  )}
                </XStack>
                <XStack gap="$2" alignItems="center">
                  <Text color={theme.colorTertiary.val} fontSize="$2">
                    {prettyCount(item.followers_count)} Followers
                  </Text>
                  <Text color={theme.colorTertiary.val}>·</Text>
                  <Text color={theme.colorTertiary.val} fontSize="$2">
                    {postCountLabel(item.statuses_count)}
                  </Text>
                  <Text color={theme.colorTertiary.val}>·</Text>
                  <Text color={theme.colorTertiary.val} fontSize="$2">
                    {item.local ? 'Joined' : 'First seen'}{' '}
                    {formatTimestampMonthYear(item.created_at)}
                  </Text>
                </XStack>
              </YStack>
            </XStack>
          </Pressable>
        </Link>
      </View>
    ),
    [theme]
  )

  const renderSeparator = useCallback(() => <View h={1} bg="$gray4" />, [])

  if (isLoading && !isFetching) {
    return <ActivityIndicator color={theme.color.val} />
  }

  if (isError) {
    return <Text>Error: {error?.message}</Text>
  }

  return (
    <SafeAreaView edges={['top', 'bottom']}>
      <FlashList
        data={dataSource}
        keyExtractor={(item) => String(item.id ?? item.acct)}
        renderItem={renderItem}
        ItemSeparatorComponent={renderSeparator}
        onScrollBeginDrag={() => Keyboard.dismiss()}
        ListEmptyComponent={renderEmptyResults}
        ListFooterComponent={() =>
          isFetching ? <ActivityIndicator /> : <View h={200} />
        }
      />
    </SafeAreaView>
  )
}
