import { imageCacheManager } from '@/utils/image/imageCacheManager'
import { isProtectedAssetUrl, resolveProtectedAssetUrl } from '@/utils/protectedAssets.js'

const PROTECTED_SELECTOR = 'img[src^="likei-protected:"]'
const PROTECTED_SOURCE_ATTR = 'data-protected-src'

async function resolveImageElement(img) {
  const originalSrc = img.getAttribute('src') || ''

  if (!isProtectedAssetUrl(originalSrc)) {
    return
  }

  if (img.getAttribute(PROTECTED_SOURCE_ATTR) === originalSrc) {
    return
  }

  img.setAttribute(PROTECTED_SOURCE_ATTR, originalSrc)
  img.setAttribute('draggable', 'false')

  try {
    const resolvedUrl = resolveProtectedAssetUrl(originalSrc)
    const objectUrl = await imageCacheManager.scheduleRequest(resolvedUrl)

    if (img.getAttribute(PROTECTED_SOURCE_ATTR) !== originalSrc) {
      return
    }

    img.src = objectUrl
  } catch (error) {
    console.warn('Failed to resolve protected image element:', error)
    img.src = resolveProtectedAssetUrl(originalSrc)
  }
}

function scanProtectedImages(rootNode = document) {
  if (!rootNode?.querySelectorAll) {
    return
  }

  rootNode.querySelectorAll(PROTECTED_SELECTOR).forEach((img) => {
    void resolveImageElement(img)
  })
}

function handleMutationRecord(record) {
  if (record.type === 'attributes' && record.target instanceof HTMLImageElement) {
    void resolveImageElement(record.target)
    return
  }

  record.addedNodes.forEach((node) => {
    if (!(node instanceof HTMLElement)) {
      return
    }

    if (node instanceof HTMLImageElement) {
      void resolveImageElement(node)
      return
    }

    scanProtectedImages(node)
  })
}

export function installProtectedAssetRuntime() {
  scanProtectedImages()

  const observer = new MutationObserver((records) => {
    records.forEach(handleMutationRecord)
  })

  observer.observe(document.documentElement, {
    subtree: true,
    childList: true,
    attributes: true,
    attributeFilter: ['src'],
  })

  window.addEventListener(
    'hashchange',
    () => {
      scanProtectedImages()
    },
    { passive: true },
  )
}
