import { type InfiniteData, useQuery, useQueryClient } from '@tanstack/react-query'
import { type ErrorBoundaryProps, router, useLocalSearchParams } from 'expo-router'
import { useEffect } from 'react'
import { Share } from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
import ArticleDetailView from 'src/components/article/ArticleDetailView'
import { ErrorState } from 'src/components/common/ErrorState'
import { useScreenMenu } from 'src/components/menu'
import { useFeature } from 'src/lib/features'
import { postQueries } from 'src/lib/queries/posts'
import { ScrollView, Spinner, useTheme, View } from 'tamagui'

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

export default function Page() {
  return <ArticleContent />
}

function ArticleContent() {
  const { id } = useLocalSearchParams<{ id: string }>()
  const theme = useTheme()
  const queryClient = useQueryClient()
  const articleIngestEnabled = useFeature('article_ingest')

  const { data, isLoading } = useQuery({
    ...postQueries.detail(id),
    placeholderData: () => {
      const staticKeys = [
        postQueries.feed().queryKey,
        postQueries.networkFeed().queryKey,
        postQueries.selfBookmarks().queryKey,
        postQueries.selfLikes().queryKey,
      ]
      for (const key of staticKeys) {
        const feed = queryClient.getQueryData<InfiniteData<any>>(key)
        const found = findPostInPages(feed, id)
        if (found) return found
      }
      const dynamicPrefixes = [
        ['statusesById'],
        ['statusesFeedById'],
        ['getHashtagByNameFeed'],
        ['search'],
      ]
      for (const prefix of dynamicPrefixes) {
        const matches = queryClient.getQueriesData<InfiniteData<any>>({
          queryKey: prefix,
        })
        for (const [, feed] of matches) {
          const found = findPostInPages(feed, id)
          if (found) return found
        }
      }
      return undefined
    },
  })

  const isArticle =
    articleIngestEnabled && data?.pf_type === 'article' && !!data?.pf_article

  // If the status loaded but isn't actually an article, forward to the
  // standard post route rather than dead-ending here. Keeps /article/[id]
  // canonical for articles and still reachable for share links.
  useEffect(() => {
    if (!isLoading && data && !isArticle) {
      router.replace(`/post/${data.id}`)
    }
  }, [isLoading, data, isArticle])

  const shareUrl = data?.pf_article?.canonical_url ?? data?.url ?? data?.uri
  const onShareArticle = () => {
    if (!shareUrl) return
    Share.share({ message: shareUrl }).catch(() => {})
  }
  const onReply = () => {
    if (data?.id) router.push(`/post/${data.id}`)
  }

  useScreenMenu(
    data?.id && isArticle
      ? {
          intents: [
            {
              kind: 'menu',
              accessibilityLabel: 'More article actions',
              items: [
                {
                  id: 'share',
                  label: 'Share',
                  icon: 'share-2',
                  onPress: onShareArticle,
                  disabled: !shareUrl,
                },
              ],
            },
            {
              kind: 'commit',
              id: 'reply',
              icon: 'message-square',
              label: 'Comment',
              onPress: onReply,
            },
          ],
        }
      : { intents: [] }
  )

  return (
    <SafeAreaView
      style={{ flex: 1, backgroundColor: theme.background.val }}
      edges={['top', 'bottom']}
    >
      {isLoading || !data || !isArticle ? (
        <View flexGrow={1} alignItems="center" justifyContent="center">
          <Spinner color="$color" />
        </View>
      ) : (
        <ScrollView flexShrink={1} contentInsetAdjustmentBehavior="automatic">
          <ArticleDetailView post={data} />
        </ScrollView>
      )}
    </SafeAreaView>
  )
}

function findPostInPages(feed: InfiniteData<any> | undefined, id: string) {
  for (const page of feed?.pages ?? []) {
    // See post/[id].tsx for the three page shapes.
    const items = Array.isArray(page) ? page : (page.items ?? page.data ?? [])
    const found = items.find((p: any) => p.id === id)
    if (found) return found
  }
  return undefined
}
