import { memo } from 'react'

/**
 * Adds a mark tag around all search hits in the text,
 * so that the given searchValues are highlighted in the text
 */
const MarkValueRenderer = memo(({ text, searchValues }: { text: string; searchValues: string[] | undefined }) => {
  if (!searchValues || searchValues.length === 0) {
    return <span>{text}</span>
  }

  // escape special characters; empty strings are removed using .filter(Boolean)
  const escapedFilterValues = searchValues
    .map((value) => {
      return value.replaceAll(/[|\\{}()[\]^$+*?.]/g, String.raw`\$&`)
    })
    .filter(Boolean)

  // no words to highlight
  if (escapedFilterValues.length === 0) {
    return <span>{text}</span>
  }

  // The split method is used to divide the "text" string into parts based on the regular expression.
  // This results in an array ("parts") where the matching words and the non-matching segments are separated.
  const regex = new RegExp(`(${escapedFilterValues.join('|')})`, 'gi')
  const parts = text.split(regex)

  return (
    <span>
      {parts.map((part, index) => {
        // to compare the parts with the words, the parts also have to be escaped
        const escapedPart = part.replaceAll(/[|\\{}()[\]^$+*?.]/g, String.raw`\$&`)
        return escapedFilterValues.some((escapedWord) => escapedPart.toLowerCase() === escapedWord.toLowerCase()) ? (
          <mark key={`${part}_${index}`} className="text-primary font-semibold bg-transparent">
            {part}
          </mark>
        ) : (
          part
        )
      })}
    </span>
  )
})

MarkValueRenderer.displayName = 'MarkCellValueRenderer'

export { MarkValueRenderer }
