import assert from "node:assert/strict"
import { describe, it } from "node:test"
import {
  computePageFlowPushes,
  computeSimulatedLayoutHeight,
  countPageFlowSpacers,
} from "./extensions/docs-page-flow-decoration.ts"
import { computePageCount } from "./docs-page-metrics.ts"

describe("docs-page-flow spacers", () => {
  const bodyAreaH = 900
  const interPageSpacer = 200

  it("inserts no spacer when content fits page 1", () => {
    assert.equal(countPageFlowSpacers([{ height: 400 }], bodyAreaH, interPageSpacer), 0)
  })

  it("inserts one spacer when a block crosses page 1", () => {
    assert.equal(
      countPageFlowSpacers([{ height: 850 }, { height: 100 }], bodyAreaH, interPageSpacer),
      1
    )
  })

  it("does not insert spacers for blocks already past page 1 boundary", () => {
    assert.equal(
      countPageFlowSpacers([{ height: 40 }, { height: 40 }], bodyAreaH, interPageSpacer),
      0
    )
  })

  it("inserts one spacer per crossing block in a layout pass", () => {
    assert.equal(
      countPageFlowSpacers([{ height: 1300 }], bodyAreaH, interPageSpacer),
      1
    )
  })

  it("inserts spacers at each page boundary for many blocks", () => {
    const blocks = Array.from({ length: 10 }, () => ({ height: 400 }))
    const pushes = computePageFlowPushes(blocks, bodyAreaH, interPageSpacer)
    assert.equal(pushes.length, 4)
    assert.deepEqual(
      pushes.map((p) => p.breakY),
      [900, 2000, 3100, 4200]
    )
  })

  it("pushes content that starts in the inter-page gap", () => {
    const pushes = computePageFlowPushes(
      [{ height: 910 }, { height: 100 }],
      bodyAreaH,
      interPageSpacer
    )
    assert.equal(pushes.length, 2)
    assert.equal(pushes[0].blockIndex, 0)
    assert.equal(pushes[1].blockIndex, 1)
    assert.equal(pushes[1].pushPx, 190)
  })

  it("does not double-count nested blocks (list model)", () => {
    const listHeight = 300
    const topLevelOnly = [{ height: 850 }, { height: listHeight }, { height: 100 }]
    const nestedOvercount = [
      { height: 850 },
      { height: listHeight },
      ...Array.from({ length: 10 }, () => ({ height: listHeight })),
      { height: 100 },
    ]

    const topLevelPushes = countPageFlowSpacers(topLevelOnly, bodyAreaH, interPageSpacer)
    const nestedPushes = countPageFlowSpacers(nestedOvercount, bodyAreaH, interPageSpacer)
    assert.equal(topLevelPushes, 1)
    assert.ok(nestedPushes > topLevelPushes)
  })

  it("simulated height matches page count across five pages", () => {
    const blocks = Array.from({ length: 10 }, () => ({ height: 400 }))
    const simH = computeSimulatedLayoutHeight(blocks, bodyAreaH, interPageSpacer)
    const pages = computePageCount(simH, {
      bodyAreaHeight: bodyAreaH,
      interPageSpacer,
      pageWidth: 0,
      pageHeight: 0,
      margins: { top: 0, right: 0, bottom: 0, left: 0 },
      headerMarginPx: 0,
      footerMarginPx: 0,
    })
    assert.equal(simH, 5200)
    assert.equal(pages, 5)
  })

  it("inserts multiple spacers for tall content split into lines", () => {
    const lineHeight = 24
    const totalH = 2500
    const lines = Math.ceil(totalH / lineHeight)
    const units = Array.from({ length: lines }, (_, i) => ({
      height: i === lines - 1 ? totalH - lineHeight * (lines - 1) : lineHeight,
    }))
    const pushes = computePageFlowPushes(units, bodyAreaH, interPageSpacer)
    assert.ok(pushes.length >= 2)
  })
})
