const SIZE_LIMIT = 32 * 1024
export const IMAGE_SIZE_LIMIT = 100 * 1024 * 1024

const ocrCache = new Map()
const imageHashCache = new Map()

export async function calculateImageHash(imageBytes) {
  const hashBuffer = await crypto.subtle.digest('SHA-256', imageBytes)
  const hashArray = Array.from(new Uint8Array(hashBuffer))
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
}

export function getOcrByHash(hash) {
  return imageHashCache.get(hash) || ''
}

export function setOcrByHash(hash, text) {
  imageHashCache.set(hash, text)
}

export function setOcrCache(filename, text) {
  ocrCache.set(filename, text)
}

export function getOcrCache(filename) {
  return ocrCache.get(filename) || ''
}

export function clearOcrCache(filename) {
  ocrCache.delete(filename)
}

export function hasOcrCache(filename) {
  return ocrCache.has(filename)
}

export function clearAllOcrCache() {
  ocrCache.clear()
}

export function calculateOcrSize(imageFilenames) {
  let total = 0
  for (const name of imageFilenames) {
    const text = ocrCache.get(name)
    if (text) total += new Blob([text]).size
  }
  return total
}

export function checkSizeLimit(docTextSize, imageFilenames) {
  const ocrSize = calculateOcrSize(imageFilenames)
  const total = docTextSize + ocrSize
  return {
    size: total,
    docSize: docTextSize,
    ocrSize: ocrSize,
    overLimit: total > SIZE_LIMIT
  }
}

export const OCR_SIZE_LIMIT = SIZE_LIMIT

export function extractTextFromOCR(ocrText, maxLen = 100) {
  if (!ocrText) return ''
  const match = ocrText.match(/TEXT:\s*([\s\S]*?)(?:KEY_DETAILS|LANGUAGE|SUMMARY|$)/i)
  let text = match ? match[1].trim() : ocrText.trim()
  if (text.toLowerCase() === '(none)') return ''
  return text.length > maxLen ? text.substring(0, maxLen) + '...' : text
}

const IMAGE_NODE_TYPES = new Set(['image', 'image-block', 'imageBlock'])

/**
 * 从 ProseMirror doc 中提取 OCR 上下文，供 AI 补全使用。
 * @param {ProseNode} doc - ProseMirror document node
 * @param {number} maxLen - OCR 文本最大长度
 * @returns {string}
 */
export function buildOcrContextForDoc(doc, maxLen = 120) {
  const lines = []

  doc.descendants((node) => {
    if (!IMAGE_NODE_TYPES.has(node.type.name)) return true
    const src = typeof node.attrs?.src === 'string' ? node.attrs.src : ''
    if (!src) return true

    const ocrText = getOcrCache(src)
    const preview = ocrText ? extractTextFromOCR(ocrText, maxLen) : ''
    if (!preview) return true

    const label = typeof node.attrs?.alt === 'string' && node.attrs.alt.trim()
      ? node.attrs.alt.trim()
      : 'image'
    lines.push(`![${label}](${src}) <OCR:${preview}>`)
    return true
  })

  return lines.join('\n')
}
