import { cloneElement, isValidElement, type ReactNode } from 'react'

/**
 * Recursively traverses a ReactNode tree and extracts the text content.
 * @param node - The ReactNode to process.
 * @returns A string containing the concatenated text content of the ReactNode tree.
 */
export function getTextContent(node: ReactNode): string {
  if (node === null || typeof node === 'boolean') return ''
  if (typeof node === 'string' || typeof node === 'number') return String(node)
  if (Array.isArray(node)) return node.map(getTextContent).join('')
  if (isValidElement(node)) {
    const props = node.props as { children?: ReactNode }
    return getTextContent(props.children)
  }
  return ''
}

/**
 * Recursively traverses a ReactNode tree and removes leading whitespace and a specified pattern from the beginning of text nodes.
 * @param node - The ReactNode to process.
 * @param pattern - The regular expression pattern to match and remove from the beginning of text nodes.
 * @returns A new ReactNode with the leading whitespace and specified pattern removed from text nodes.
 */
export function stripLeadingMatch(node: ReactNode, pattern: RegExp): ReactNode {
  if (typeof node === 'string') {
    const trimmed = node.replace(/^\s+/, '')
    if (pattern.test(trimmed)) {
      return trimmed.replace(pattern, '').replace(/^\s+/, '')
    }
    return node
  }
  if (Array.isArray(node)) {
    let stripped = false
    return node.map((child) => {
      if (stripped) return child
      if (typeof child === 'string' && child.trim() === '') return child // skip whitespace nodes
      if (typeof child === 'string') {
        const trimmed = child.replace(/^\s+/, '')
        if (pattern.test(trimmed)) {
          stripped = true
          return trimmed.replace(pattern, '').replace(/^\s+/, '')
        }
        return child
      }
      if (isValidElement(child)) {
        stripped = true
        return stripLeadingMatch(child, pattern)
      }
      return child
    })
  }
  if (isValidElement(node)) {
    const props = node.props as { children?: ReactNode }
    return cloneElement(node, {}, stripLeadingMatch(props.children, pattern))
  }
  return node
}
