export function extractTextFromHtml(html) {
  const parser = new DOMParser()
  const doc = parser.parseFromString(html, 'text/html')
  doc.querySelectorAll('style, script').forEach((el) => el.remove())
  doc.body?.querySelectorAll('*').forEach((el) => {
    el.before(doc.createTextNode(' '))
    el.after(doc.createTextNode(' '))
  })
  return (doc.body?.textContent || '')
    .replace(/\u00a0/g, ' ')
    .replace(/[«»„\u201C\u201D\u2018\u2019]/g, ' ')
    .replace(/\{%[\s\S]*?%\}/g, ' ')
    .replace(/\{\{[^}]*\}\}|@\{[^}]*\}|\$\{[^}]*\}/g, ' ')
    .replace(/\s+/g, ' ')
    .replace(/(?:[а-яёА-ЯЁa-zA-Z]+:\s*){4,}/g, ' ')
    .replace(/(.{10,60})\1+/g, '$1')
    .replace(/\s+/g, ' ')
    .trim()
}

export function injectSpellMarks(html, errors) {
  if (!errors.length) return html
  const wordMap = new Map()
  for (const err of errors) {
    if (!wordMap.has(err.word)) {
      let tip
      if (err.code === 2) {
        tip = 'Повторяющееся слово'
      } else if (err.s && err.s.length && err.s[0] !== err.word) {
        tip = '→ ' + err.s.join(', ')
      } else {
        tip = 'Неизвестное слово'
      }
      wordMap.set(err.word, tip)
    }
  }
  const unique = [...wordMap.keys()].sort((a, b) => b.length - a.length)
  const css =
    '<style>mark.va-spell{background:rgba(224,82,82,0.12);text-decoration:underline wavy #e05252;text-decoration-skip-ink:none;color:inherit;cursor:help;}</style>'
  let result = html.includes('</head>') ? html.replace('</head>', css + '</head>') : css + html
  result = result.replace(/(<[^>]*>)|([^<]+)/g, (match, tag, text) => {
    if (tag) return tag
    if (!text || !text.trim()) return text
    let replaced = text
    for (const word of unique) {
      const tip = wordMap.get(word)
      const escaped = word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
      const titleAttr = tip ? ` title="${tip.replace(/"/g, '&quot;')}"` : ''
      replaced = replaced.replace(
        new RegExp(`(?<![а-яёА-ЯЁa-zA-Z0-9])${escaped}(?![а-яёА-ЯЁa-zA-Z0-9])`, 'g'),
        `<mark class="va-spell"${titleAttr}>$&</mark>`
      )
    }
    return replaced
  })
  return result
}
