import { TopicProps } from '@junwon/centum'
import { Button, Input, Text, XStack, YStack, isWeb } from '@my/ui'
import { ChevronRight, Search, X, Plus } from '@tamagui/lucide-icons'
import { debounce } from 'lodash'
import { useCallback, useEffect, useState } from 'react'
import { StyleSheet } from 'react-native'

import usePageOpener from '../../utils/catalog/usePageOpener'

const linkColor = '#06CAEB'

async function searchCatalogForTopics(database, searchQuery: string): Promise<TopicProps[]> {
  if (searchQuery.length < 1) {
    return []
  }

  const reformulatedSearchQuery = `"${searchQuery.replace(/"/g, '\\"').replace(/ /g, '+')}":*`

  const { data, error } = await database
    .from('topics')
    .select('*')
    .textSearch('text_search_vector', reformulatedSearchQuery)
    .eq('allowed_in_site', true)
    .eq('disallowed_in_site', false)
    .limit(10)
  if (error) {
    console.error('Error searching topics:', error)
    return []
  }
  return data
}

const SearchResultItem = ({
  topic,
  database,
  insertDataAfterIndex,
  handleEndEditing,
}: {
  topic: TopicProps
  database: any
  insertDataAfterIndex: Function
  handleEndEditing: Function
}) => {
  const { openTopicPage } = usePageOpener()
  const title = topic.topic
  const subtitle = topic.is_presentable ? topic.intro : 'Ask Santana'

  const searchResultItemStyle = {
    overflow: 'hidden',
    textOverflow: 'ellipsis',
    ellipsizeMode: 'tail',
    whiteSpace: 'nowrap',
    letterSpacing: 0.3,
  }

  const titleFont = isWeb
    ? { fontFamily: 'Spline+Sans', fontWeight: 400 }
    : { fontFamily: 'SplineSansRegular' }

  const subtitleFont = isWeb
    ? { fontFamily: 'Spline+Sans', fontWeight: 300 }
    : { fontFamily: 'SplineSansLight' }

  const openTopic = () => {
    openTopicPage(topic.topic)
    handleEndEditing()
  }

  return (
    <XStack ai="center" jc="space-between" onPress={openTopic}>
      <YStack backgroundColor="$colorTransparent" f={1} gap="$1">
        <Text
          style={{ ...searchResultItemStyle, ...titleFont }}
          numberOfLines={1}
          fontSize="$5"
          transform={[{ scaleX: 1.03 }, { scaleY: 0.95 }]}
        >
          {title}
        </Text>
        <Text
          style={{ ...searchResultItemStyle, ...subtitleFont }}
          numberOfLines={1}
          color="$gray9"
          fontSize="$5"
          transform={[{ scaleX: 1.03 }, { scaleY: 0.95 }]}
        >
          {subtitle}
        </Text>
      </YStack>
      {topic.is_presentable ? (
        <ChevronRight color={linkColor} size="$1" style={{ flexShrink: 0 }} marginHorizontal={10} />
      ) : (
        <Plus color={'$gray9'} size="$1" style={{ flexShrink: 0 }} marginHorizontal={10} />
      )}
    </XStack>
  )
}

const styles = StyleSheet.create({
  searchBarFont: isWeb
    ? {
        fontFamily: 'Spline+Sans',
        fontWeight: '300',
      }
    : {
        fontFamily: 'SplineSansLight',
      },
  input: {
    letterSpacing: 0.3,
    flex: 1,
    textDecorationLine: 'none',
  },
})

export const SearchBar = ({ database, insertDataAfterIndex }) => {
  const [searchQuery, setSearchQuery] = useState<string>('')
  const [isFocused, setIsFocused] = useState<boolean>(false)
  const [searchResults, setSearchResults] = useState<TopicProps[]>([])

  const handleSearchChange = (query: string) => {
    setSearchQuery(query)
    debouncedSearch(query)
  }

  const debouncedSearch = useCallback(
    debounce(async (query: string) => {
      const results = await searchCatalogForTopics(database, query)
      setSearchResults(results)
    }, 300),
    [database]
  )

  const handleSearchSubmit = () => {
    setIsFocused(false)
  }

  const handleEndEditing = () => {
    setSearchQuery('')
    setSearchResults([])
    setIsFocused(false)
  }

  useEffect(() => {
    return () => {
      debouncedSearch.cancel()
    }
  }, [debouncedSearch])

  return (
    <YStack width="103%" gap="$5">
      <XStack
        fd="row"
        ai="center"
        backgroundColor="$gray5"
        borderRadius={100}
        paddingHorizontal={16}
      >
        <Input
          placeholder={isFocused ? '' : 'Search the catalog'}
          placeholderTextColor="$gray9"
          value={searchQuery}
          onChangeText={handleSearchChange}
          onSubmitEditing={handleSearchSubmit}
          onFocus={() => setIsFocused(true)}
          onBlur={() => {
            if (searchQuery.length === 0) {
              setIsFocused(false)
            }
          }}
          style={[styles.searchBarFont, styles.input]}
          fontSize="$5"
          transform={[{ scaleX: 1.03 }, { scaleY: 0.95 }]}
          height="$6"
          borderWidth={0}
          backgroundColor="$colorTransparent"
          caretColor="$gray8"
          focusVisibleStyle={{ outlineWidth: 0 }}
          enterKeyHint="search"
        />
        <Button unstyled onPress={handleEndEditing}>
          {isFocused ? (
            <X marginHorizontal="$4" color="$gray9" size="$1" />
          ) : (
            <Search marginHorizontal="$4" color="$gray9" size="$1" />
          )}
        </Button>
      </XStack>
      {searchQuery.length > 0 && (
        <YStack gap="$5" pl="$6" pr="$5">
          {!searchResults.some(
            (result) => result.topic.toLowerCase() === searchQuery.toLowerCase()
          ) && (
            <SearchResultItem
              key="ask-for-topic"
              topic={{
                topic: searchQuery,
                intro: 'Add topic to the catalog',
                is_presentable: false,
              }}
              database={database}
              insertDataAfterIndex={insertDataAfterIndex}
              handleEndEditing={handleEndEditing}
            />
          )}
          {searchResults.map((result, index) => (
            <SearchResultItem
              key={index}
              topic={result}
              database={database}
              insertDataAfterIndex={insertDataAfterIndex}
              handleEndEditing={handleEndEditing}
            />
          ))}
        </YStack>
      )}
    </YStack>
  )
}
