/**
 * Composable para búsqueda fuzzy de texto
 * Normaliza acentos y es tolerante a typos básicos
 */
export const useFuzzySearch = () => {
  /**
   * Normaliza un texto para comparación:
   * - Convierte a minúsculas
   * - Elimina acentos/diacríticos
   * - Elimina espacios extra
   */
  const normalize = (text: string): string => {
    return text
      .toLowerCase()
      .normalize('NFD')
      .replace(/[\u0300-\u036f]/g, '')
      .trim()
  }

  /**
   * Verifica si el texto contiene la query (fuzzy)
   * Retorna true si hay match
   */
  const fuzzyMatch = (text: string, query: string): boolean => {
    if (!query) return true
    if (!text) return false

    const normalizedText = normalize(text)
    const normalizedQuery = normalize(query)

    // Match exacto (substring)
    if (normalizedText.includes(normalizedQuery)) return true

    // Match por palabras - cada palabra de la query debe coincidir con alguna palabra del texto
    const textWords = normalizedText.split(/\s+/)
    const queryWords = normalizedQuery.split(/\s+/)

    return queryWords.every(queryWord =>
      textWords.some(textWord =>
        textWord.startsWith(queryWord) || textWord.includes(queryWord)
      )
    )
  }

  /**
   * Calcula un score de relevancia (0-100)
   * Mayor score = mejor match
   */
  const fuzzyScore = (text: string, query: string): number => {
    if (!query) return 100
    if (!text) return 0

    const normalizedText = normalize(text)
    const normalizedQuery = normalize(query)

    // Match exacto completo
    if (normalizedText === normalizedQuery) return 100

    // Match al inicio
    if (normalizedText.startsWith(normalizedQuery)) return 90

    // Match exacto (substring)
    if (normalizedText.includes(normalizedQuery)) {
      const position = normalizedText.indexOf(normalizedQuery)
      return 80 - (position / normalizedText.length) * 20
    }

    // Match por palabras
    const textWords = normalizedText.split(/\s+/)
    const queryWords = normalizedQuery.split(/\s+/)

    let matchedWords = 0
    let startMatches = 0

    queryWords.forEach(queryWord => {
      const match = textWords.find(textWord =>
        textWord.startsWith(queryWord) || textWord.includes(queryWord)
      )
      if (match) {
        matchedWords++
        if (match.startsWith(queryWord)) startMatches++
      }
    })

    if (matchedWords === 0) return 0

    const matchRatio = matchedWords / queryWords.length
    const startBonus = startMatches / queryWords.length * 10

    return Math.round(matchRatio * 60 + startBonus)
  }

  /**
   * Filtra y ordena una lista por relevancia de búsqueda
   */
  const filterAndSort = <T>(
    items: T[],
    query: string,
    getText: (item: T) => string
  ): T[] => {
    if (!query) return items

    return items
      .map(item => ({
        item,
        score: fuzzyScore(getText(item), query)
      }))
      .filter(({ score }) => score > 0)
      .sort((a, b) => b.score - a.score)
      .map(({ item }) => item)
  }

  return {
    normalize,
    fuzzyMatch,
    fuzzyScore,
    filterAndSort
  }
}
