import type { PptxElement } from "./pptxTypes"

export function getNumber(value: unknown) {
  const n = Number(value)
  return Number.isFinite(n) ? n : 0
}

export function parsePx(value: unknown) {
  const n = Number.parseFloat(String(value ?? ""))
  return Number.isFinite(n) ? n : 0
}

export function getCacheKey(slideIndex: number, cacheId: string) {
  return `${slideIndex}-${cacheId}`
}

export function sanitizeHtml(html: string) {
  if (!html) return ""
  try {
    const parser = new DOMParser()
    const doc = parser.parseFromString(html, "text/html")

    const forbidden = ["script", "style", "iframe", "object", "embed", "link", "meta"]
    forbidden.forEach((tag) => {
      doc.querySelectorAll(tag).forEach((node) => node.remove())
    })

    doc.querySelectorAll("*").forEach((node) => {
      Array.from(node.attributes).forEach((attr) => {
        const name = attr.name.toLowerCase()
        const value = String(attr.value || "").trim().toLowerCase()
        if (name.startsWith("on")) node.removeAttribute(attr.name)
        if ((name === "href" || name === "src") && value.startsWith("javascript:")) {
          node.removeAttribute(attr.name)
        }
      })

      const style = node.getAttribute("style")
      if (style) {
        let replaced = style.replace(/font-size\s*:\s*([\d.]+)pt/gi, (_m, v) => {
          const n = Number(v)
          if (!Number.isFinite(n)) return _m
          const px = (n * 96) / 72
          return `font-size: ${px.toFixed(3).replace(/\.0+$/, "").replace(/(\.\d*?)0+$/, "$1")}px`
        })

        // 处理两端对齐，增加 text-align-last 和 text-justify
        if (/text-align\s*:\s*justify/i.test(replaced)) {
          if (!/text-align-last/i.test(replaced)) {
            replaced += ";text-align-last:justify"
          }
          if (!/text-justify/i.test(replaced)) {
            replaced += ";text-justify:inter-character"
          }
        }

        if (replaced !== style) node.setAttribute("style", replaced)
      }
    })

    return doc.body.innerHTML
  } catch {
    return html
  }
}

export function getElementKey(el: PptxElement, elementIndex: number) {
  const stable = getNumber(el.order) || elementIndex
  return `${el.type || "el"}-${stable}`
}

export function getElementCacheId(el: PptxElement, elementIndex: number, parentCacheId?: string) {
  const stable = getNumber(el.order) || elementIndex
  const t = String(el.type || "el")
  const self = `${t}-${stable}`
  return parentCacheId ? `${parentCacheId}/${self}` : self
}

export function getElementBorderRadius(el: PptxElement) {
  const candidates = [el.radius, el.cornerRadius, el.rx]
  const r = candidates.map(getNumber).find((n) => n > 0) || 0
  return r ? `${r}px` : undefined
}

export type BorderInfo = {
  color: string
  width: number
  dasharray?: string
}

export function getBorderInfo(el: PptxElement): BorderInfo {
  const directColor = String(el.borderColor ?? el.stroke ?? el.lineColor ?? "")
  const directWidth = getNumber(el.borderWidth ?? el.strokeWidth ?? el.lineWidth)
  const directDash = String(el.borderStrokeDasharray ?? el.strokeDasharray ?? el.dasharray ?? "")

  const borderObj = el.border && typeof el.border === "object" ? el.border : null
  const lineObj = el.line && typeof el.line === "object" ? el.line : null
  const fallbackColor = String(borderObj?.color ?? lineObj?.color ?? "")
  const fallbackWidth = getNumber(borderObj?.width ?? lineObj?.width)
  const fallbackDash = String(borderObj?.dasharray ?? lineObj?.dasharray ?? "")

  const color = directColor || fallbackColor
  const width = directWidth || fallbackWidth
  const dasharray = (directDash && directDash !== "0" ? directDash : "") || (fallbackDash && fallbackDash !== "0" ? fallbackDash : "")
  return {
    color: color || "transparent",
    width: Math.max(0, width),
    dasharray: dasharray || undefined,
  }
}

function getPlaceholderMeta(el: PptxElement) {
  const ph = (el as any)?.ph ?? (el as any)?.placeholder ?? (el as any)?.placeHolder ?? null
  const type = String(ph?.type ?? ph?.phType ?? (el as any)?.phType ?? (el as any)?.placeholderType ?? "")
    .trim()
    .toLowerCase()
  const idx = getNumber(ph?.idx ?? ph?.phIdx ?? (el as any)?.phIdx ?? (el as any)?.idx ?? (el as any)?.placeholderIdx ?? (el as any)?.phIndex)
  const id = String(ph?.id ?? (el as any)?.phId ?? (el as any)?.placeholderId ?? "").trim()
  if (!type && !idx && !id) return null
  return { type, idx, id }
}

export function getPlaceholderKey(el: PptxElement) {
  const meta = getPlaceholderMeta(el)
  if (!meta) return ""
  const tail = meta.id || (meta.idx ? String(meta.idx) : "")
  return tail ? `${meta.type || "ph"}:${tail}` : `${meta.type || "ph"}`
}

export function isPlaceholderHint(content: string) {
  const s = String(content || "").trim()
  if (!s) return false
  return /click to add/i.test(s) || /单击.*添加/.test(s) || /点击.*添加/.test(s) || /添加(标题|文本|内容)/.test(s)
}

