import { useMemo } from 'preact/hooks'
import { Message } from '../atoms/message.js'
import { Annotation } from '../routing/annotation.js'
import h from '../shared/h.js'
import { isPublish } from '../shared/wcm-mode.js'

function isInvalidAttribute (name) {
  try {
    document.createAttribute(name)
    return false
  } catch {
    return true
  }
}

export function WebComponent ({ _model, ...props }) {
  const { links } = _model
  const src = links?.[0]?.value
  const [elementName, attrs] = useMemo(() => [
    src
      ?.replace(/\?.*/, '')
      .split('/')
      .pop()
      .split('.')
      .shift()
      .replaceAll(/[^a-zA-Z-]/g, ''),
    links
      .slice(1)
      .reduce((obj, link) => ({ ...obj, [link.name]: link.value }), {})
  ], [src, links])

  // Validate attrs.
  const invalidAttrNames = useMemo(() => Object.keys(attrs).filter(isInvalidAttribute), [attrs])

  // Allow only same origin script.
  if (!src || globalThis.origin !== new URL(src, globalThis.origin).origin) {
    return h(Message, props, 'Invalid script source.')
  }

  // Invalid attrs.
  if (invalidAttrNames.length) {
    const formattedNames = invalidAttrNames.map(attrName => `"${attrName}"`).join(', ')
    return h(Message, props, `Invalid attribute name: ${formattedNames}`)
  }

  return h('div', { ...props, className: 'w-full h-full' },
    !isPublish && h('div', { className: 'relative' },
      h(Annotation, elementName) // Annotate web components on author.
    ),
    h('script', { src, type: 'module', crossorigin: 'anonymous', async: true }),
    h(elementName, { ...attrs, className: 'w-full h-full' })
  )
}
