// Serialises and embeds the deck outline into a Marp-generated index.html.
// Values containing no nested objects are inlined on one line (e.g. items, slide_range arrays).
// Keys are ordered by importance (slug/title first), with unknown keys alphabetical at the end.
export function serializeOutline(outline) {
  return stringify(outline).replace(/<\//g, '<\\/')
}

const KEY_PRIORITY = ['slug', 'title', 'description', 'kind', 'type', 'duration', 'slide_range', 'items', 'days', 'schedule']

function sortedKeys(obj) {
  return Object.keys(obj).sort((a, b) => {
    const ai = KEY_PRIORITY.indexOf(a)
    const bi = KEY_PRIORITY.indexOf(b)
    if (ai === -1 && bi === -1) return a.localeCompare(b)
    if (ai === -1) return 1
    if (bi === -1) return -1
    return ai - bi
  })
}

function isLeaf(value) {
  if (value === null || typeof value !== 'object') return true
  if (Array.isArray(value)) return value.every(v => v === null || typeof v !== 'object')
  return Object.values(value).every(
    v => v === null || typeof v !== 'object' ||
    (Array.isArray(v) && v.every(x => x === null || typeof x !== 'object'))
  )
}

function inline(value) {
  if (value === null || typeof value !== 'object') return JSON.stringify(value)
  if (Array.isArray(value)) return `[${value.map(inline).join(', ')}]`
  const entries = sortedKeys(value).map(k => `${JSON.stringify(k)}: ${inline(value[k])}`)
  return `{ ${entries.join(', ')} }`
}

function stringify(value, depth = 0) {
  if (isLeaf(value)) return inline(value)
  const pad = '  '.repeat(depth)
  const inner = '  '.repeat(depth + 1)
  if (Array.isArray(value)) {
    const items = value.map(v => `${inner}${stringify(v, depth + 1)}`)
    return `[\n${items.join(',\n')}\n${pad}]`
  }
  const entries = sortedKeys(value).map(k => `${inner}${JSON.stringify(k)}: ${stringify(value[k], depth + 1)}`)
  return `{\n${entries.join(',\n')}\n${pad}}`
}

export function injectOutline(html, outline) {
  const tag = `<script type="application/json" id="deck-outline">${serializeOutline(outline)}</script>`
  return html.replace('</head>', `${tag}\n</head>`)
}
