import type { Root, Element, ElementContent, Text } from 'hast'
import type { Plugin } from 'unified'
import { visit } from 'unist-util-visit'

/**
 * A rehype plugin that transforms paragraphs containing a leading "Term:" into
 * definition lists. For example, a paragraph like "Term: Definition" will be
 * transformed into a <dl> element with a <dt> for the term and a <dd> for the
 * definition.
 */
export const rehypeDefinition: Plugin<[], Root> = () => (tree: Root) => {
  visit(tree, 'element', (node: Element, index, parent) => {
    if (!parent || typeof index !== 'number') return
    if (node.tagName !== 'p') return

    const children = node.children

    let splitIndex = -1
    let colonIndex = -1
    for (let i = 0; i < children.length; i++) {
      const child = children[i]
      if (child.type === 'text') {
        const idx = child.value.indexOf(':')
        if (idx !== -1) {
          splitIndex = i
          colonIndex = idx
          break
        }
      }
    }

    if (splitIndex === -1) return

    const splitText = children[splitIndex] as Text
    const beforeColon = splitText.value.slice(0, colonIndex)
    const afterColon = splitText.value.slice(colonIndex + 1).replace(/^\s+/, '')

    const termChildren: ElementContent[] = [
      ...children.slice(0, splitIndex),
      ...(beforeColon ? [{ type: 'text', value: beforeColon } as Text] : []),
    ]

    const definitionChildren: ElementContent[] = [
      ...(afterColon ? [{ type: 'text', value: afterColon } as Text] : []),
      ...children.slice(splitIndex + 1),
    ]

    if (termChildren.length === 0 || definitionChildren.length === 0) return

    const dlNode: Element = {
      type: 'element',
      tagName: 'dl',
      properties: {},
      children: [
        {
          type: 'element',
          tagName: 'dt',
          properties: {},
          children: termChildren,
        },
        {
          type: 'element',
          tagName: 'dd',
          properties: {},
          children: definitionChildren,
        },
      ],
    }

    parent.children[index] = dlNode
  })
}
