import { FlashList } from '@shopify/flash-list'
import { useQuery } from '@tanstack/react-query'
import type { ErrorBoundaryProps } from 'expo-router'
import { router, useLocalSearchParams } from 'expo-router'
import { useCallback, useMemo } from 'react'
import { ActivityIndicator } from 'react-native'
import { onMentionPressMethod } from 'src/components/common/AutolinkText'
import { ErrorState } from 'src/components/common/ErrorState'
import ExpandableText from 'src/components/common/ExpandableText'
import StatusContent from 'src/components/common/StatusContent'
import { ScreenScrollContainer } from 'src/components/layout'
import { postQueries } from 'src/lib/queries/posts'
import { htmlToTextWithLineBreaks, timeAgo } from 'src/utils'
import { Separator, Text, useTheme, View, XStack, YStack } from 'tamagui'

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

export default function Page() {
  const { id } = useLocalSearchParams<{ id: string }>()
  const theme = useTheme()

  const { isPending, isError, data, error } = useQuery(postQueries.history(id))

  const filteredData = useMemo(() => data, [data])

  const getDiff = (oldContent: string, newContent: string) => {
    const oldWords = oldContent.split(/\s+/)
    const newWords = newContent.split(/\s+/)
    const diff = []
    let i = 0
    let j = 0

    while (i < oldWords.length && j < newWords.length) {
      if (oldWords[i] === newWords[j]) {
        diff.push({ text: oldWords[i], type: 'same' })
        i++
        j++
      } else if (oldWords[i] !== newWords[j]) {
        diff.push({ text: oldWords[i], type: 'removed' })
        diff.push({ text: newWords[j], type: 'added' })
        i++
        j++
      }
    }

    while (i < oldWords.length) {
      diff.push({ text: oldWords[i], type: 'removed' })
      i++
    }
    while (j < newWords.length) {
      diff.push({ text: newWords[j], type: 'added' })
      j++
    }

    return diff
  }

  const HighlightedDiff = ({
    oldContent,
    newContent,
  }: {
    oldContent: string
    newContent: string
  }) => {
    const diff = getDiff(oldContent, newContent)

    return (
      <>
        {diff.map((part, index) => (
          <Text
            key={index}
            flexWrap="wrap"
            fontSize="$3"
            allowFontScaling={false}
            color={
              part.type === 'added'
                ? 'green'
                : part.type === 'removed'
                  ? '#D55453'
                  : theme.color.val
            }
            backgroundColor={
              part.type === 'added'
                ? '#F4FCF6'
                : part.type === 'removed'
                  ? '#FCEFEF'
                  : undefined
            }
          >
            {part.text}
            <Text> </Text>
          </Text>
        ))}
      </>
    )
  }
  // History items have no `account.url` on the version snapshot — local-vs-
  // remote disambiguation isn't reachable from here, so an empty string is
  // passed and `onMentionPressMethod` treats every mention as remote, which
  // matches how the canonical post detail behaves on a federated mention with
  // no host attached. Hashtag/mention routing matches the rest of the app.
  const onHashtagPress = useCallback((tag: string) => {
    router.push(`/hashtag/${tag}`)
  }, [])
  const onMentionPress = useMemo(
    () =>
      onMentionPressMethod(
        (username: string) => router.push(`/profile/0?byUsername=${username}`),
        ''
      ),
    []
  )

  const RenderItem = useCallback(
    ({ item, index }: { item: any; index: any }) => {
      let prevData = index > 0 ? data[index - 1]?.content : null
      return (
        <View p="$5" bg={theme.backgroundTertiary.val}>
          <YStack gap="$2">
            <XStack gap="$3" flexWrap="wrap">
              <Text fontWeight="bold" color={theme.colorTertiary.val}>
                Version #{index + 1}
              </Text>
              <Text color={theme.colorTertiary.val}>
                Post edited {timeAgo(item?.created_at)}
              </Text>
            </XStack>
            {index > 0 ? (
              // Diff fidelity wins over link-tap in the diff view —
              // <HighlightedDiff> renders the word diff with red/green
              // backgrounds that StatusContent's API can't express. Keep the
              // ExpandableText wrapper for the View More / View Less toggle.
              <ExpandableText
                text={htmlToTextWithLineBreaks(item.content)}
                thresholdChars={280}
                maxLines={3}
              >
                <HighlightedDiff
                  oldContent={htmlToTextWithLineBreaks(prevData)}
                  newContent={htmlToTextWithLineBreaks(item.content)}
                />
              </ExpandableText>
            ) : (
              <StatusContent
                html={item.content}
                onHashtagPress={onHashtagPress}
                onMentionPress={onMentionPress}
                thresholdChars={280}
              />
            )}
          </YStack>
        </View>
      )
    },
    [data, theme, onHashtagPress, onMentionPress]
  )
  if (isPending) {
    return (
      <View flexGrow={1} mt="$5">
        <ActivityIndicator color={theme.color.val} />
      </View>
    )
  }

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

  return (
    <ScreenScrollContainer variant="flashlist" header="Edit History">
      {(scrollProps) => (
        <FlashList
          data={filteredData}
          renderItem={RenderItem}
          ItemSeparatorComponent={Separator}
          {...scrollProps}
        />
      )}
    </ScreenScrollContainer>
  )
}
