/**
 * Word-processor formats routed to the TipTap rich-text editor.
 * Cell/slide/diagram formats stay on OnlyOffice.
 */
export const RICHTEXT_EXTENSIONS = new Set([
  "doc",
  "docm",
  "docx",
  "dot",
  "dotm",
  "dotx",
  "epub",
  "fb2",
  "fodt",
  "htm",
  "html",
  "hwp",
  "hwpx",
  "md",
  "mht",
  "mhtml",
  "odt",
  "ott",
  "rtf",
  "stw",
  "sxw",
  "txt",
  "wps",
  "wpt",
  "xml",
  "ultidoc",
] as const)

export const ULTIDOC_EXTENSION = "ultidoc.json"

const RICHTEXT_MIME_HINTS = [
  "wordprocessingml",
  "msword",
  "opendocument.text",
  "text/html",
  "text/plain",
  "text/markdown",
  "application/rtf",
  "application/epub",
] as const

export function fileExtension(name: string): string {
  const base = name.split("/").pop() ?? name
  const lower = base.toLowerCase()
  if (lower.endsWith(`.${ULTIDOC_EXTENSION}`)) return ULTIDOC_EXTENSION
  const i = base.lastIndexOf(".")
  if (i <= 0) return ""
  return base.slice(i + 1).toLowerCase()
}

export function isRichTextExtension(ext: string): boolean {
  const normalized = ext.toLowerCase()
  if (normalized === ULTIDOC_EXTENSION) return true
  return RICHTEXT_EXTENSIONS.has(normalized as (typeof RICHTEXT_EXTENSIONS extends Set<infer T> ? T : never))
}

export function isRichTextMime(mime: string): boolean {
  const m = mime.toLowerCase()
  return RICHTEXT_MIME_HINTS.some((hint) => m.includes(hint))
}

export function isRichTextFile(file: { name: string; mime_type?: string }): boolean {
  const ext = fileExtension(file.name)
  if (ext && isRichTextExtension(ext)) return true
  const mime = (file.mime_type ?? "").toLowerCase()
  if (mime && isRichTextMime(mime)) return true
  return false
}

export function isUltidocPath(path: string): boolean {
  return path.toLowerCase().endsWith(`.${ULTIDOC_EXTENSION}`)
}

/** Sidecar path for a source document, e.g. /docs/report.docx → /docs/report.ultidoc.json */
export function sidecarPathForSource(sourcePath: string): string {
  const normalized = sourcePath.replace(/\/+/g, "/")
  const slash = normalized.lastIndexOf("/")
  const dir = slash >= 0 ? normalized.slice(0, slash) : ""
  const fileName = slash >= 0 ? normalized.slice(slash + 1) : normalized
  const dot = fileName.lastIndexOf(".")
  const base = dot > 0 ? fileName.slice(0, dot) : fileName
  const sidecarName = `${base}.${ULTIDOC_EXTENSION}`
  if (!dir) return `/${sidecarName}`
  return `${dir}/${sidecarName}`.replace(/\/+/g, "/")
}

/** Source path from an ultidoc sidecar name (best-effort). */
export function guessSourcePathFromSidecar(sidecarPath: string, knownExtensions: string[]): string | null {
  if (!isUltidocPath(sidecarPath)) return null
  const normalized = sidecarPath.replace(/\/+/g, "/")
  const slash = normalized.lastIndexOf("/")
  const dir = slash >= 0 ? normalized.slice(0, slash) : ""
  const fileName = slash >= 0 ? normalized.slice(slash + 1) : normalized
  const base = fileName.slice(0, -(ULTIDOC_EXTENSION.length + 1))
  for (const ext of knownExtensions) {
    const candidate = `${base}.${ext}`
    return dir ? `${dir}/${candidate}` : `/${candidate}`
  }
  return null
}
