import React, { useMemo } from 'react'
import { sanitizeExerciseRichDisplayHtml } from '../utils/exerciseRichTextSanitize'
import ExerciseMediaEmbed from './ExerciseMediaEmbed'

function isTrashHidden(m) {
  return String(m?.asset_lifecycle_state || 'active').toLowerCase() === 'trash_hidden'
}

function buildVisibleMediaMap(mediaList) {
  const map = new Map()
  for (const m of mediaList || []) {
    if (!m || m.id == null || isTrashHidden(m)) continue
    map.set(Number(m.id), m)
  }
  return map
}

function domToReactNodes(node, exerciseId, mediaById, path) {
  if (node.nodeType === Node.TEXT_NODE) {
    const t = node.textContent
    return t ? t : null
  }
  if (node.nodeType !== Node.ELEMENT_NODE) return null

  const el = node
  const tag = el.tagName.toLowerCase()
  const key = path.join('.')

  if (tag === 'span' && el.getAttribute('data-shinkan-exercise-media')) {
    const raw = el.getAttribute('data-shinkan-exercise-media')
    const mid = parseInt(raw, 10)
    if (!Number.isFinite(mid) || mid < 1) {
      return (
        <span key={key} className="shinkan-inline-media-missing" style={{ color: 'var(--text3)', fontSize: '0.9em' }}>
          [Ungültiger Medienverweis]
        </span>
      )
    }
    const media = mediaById.get(mid)
    if (!media) {
      return (
        <span key={key} className="shinkan-inline-media-missing" style={{ color: 'var(--text3)', fontSize: '0.9em' }}>
          [Medium nicht verfügbar]
        </span>
      )
    }
    const rawSize = (el.getAttribute('data-shinkan-exercise-media-size') || 'medium').toLowerCase().trim()
    const layoutSize = rawSize === 'small' || rawSize === 'full' ? rawSize : 'medium'
    const wrapClass =
      layoutSize === 'small'
        ? 'shinkan-inline-media-wrap shinkan-inline-media-wrap--sm'
        : layoutSize === 'full'
          ? 'shinkan-inline-media-wrap shinkan-inline-media-wrap--full'
          : 'shinkan-inline-media-wrap shinkan-inline-media-wrap--md'
    const lc = String(media.asset_lifecycle_state || 'active').toLowerCase()
    return (
      <span key={key} className={wrapClass} style={{ display: 'inline-block', verticalAlign: 'top' }}>
        {lc === 'trash_soft' && (
          <span style={{ fontSize: '0.75rem', color: 'var(--danger)', display: 'block', marginBottom: '4px' }}>
            Dieses Medium ist im Papierkorb.
          </span>
        )}
        <ExerciseMediaEmbed exerciseId={exerciseId} media={media} layoutSize={layoutSize} />
      </span>
    )
  }

  const children = []
  const childNodes = Array.from(el.childNodes)
  childNodes.forEach((ch, i) => {
    const sub = domToReactNodes(ch, exerciseId, mediaById, [...path, String(i)])
    if (sub != null && sub !== false) children.push(sub)
  })

  const props = { key }
  if (tag === 'a' && el.getAttribute('href')) {
    props.href = el.getAttribute('href')
    props.target = '_blank'
    props.rel = 'noreferrer'
  }
  return React.createElement(tag, props, children.length ? children : null)
}

/**
 * Zentraler Anzeige-Pfad für Übungs-Rich-Text inkl. §11 Inline-Medien.
 * @param {{ html?: string|null, exerciseId?: number|null, media?: object[]|null, className?: string }} props
 */
export default function ExerciseRichTextBlock({ html, exerciseId, media, className = '' }) {
  const safe = useMemo(() => sanitizeExerciseRichDisplayHtml(html), [html])
  const mediaById = useMemo(() => buildVisibleMediaMap(media), [media])

  const body = useMemo(() => {
    if (!safe.trim()) return null
    const tpl = document.createElement('template')
    tpl.innerHTML = safe
    const nodes = []
    Array.from(tpl.content.childNodes).forEach((ch, i) => {
      const r = domToReactNodes(ch, exerciseId, mediaById, [String(i)])
      if (r != null) nodes.push(r)
    })
    return nodes
  }, [safe, exerciseId, mediaById])

  if (!body || body.length === 0) return null

  return <div className={`rich-text-content ${className}`.trim()}>{body}</div>
}
