import assert from "node:assert/strict"
import { describe, it } from "node:test"
import {
  borderSzToPx,
  bordersToLayoutCss,
  buildPageSetupFromDraft,
  cmToMm,
  draftFromPageSetup,
  matchPageFormatId,
  mmToCm,
  parseWordBorderSide,
  resolveDocumentPageLayout,
  twipsToMm,
} from "./doc-page-setup.ts"

describe("doc-page-setup", () => {
  it("converts A4 twips to millimeters", () => {
    assert.ok(Math.abs(twipsToMm(11906) - 210) < 1)
    assert.ok(Math.abs(twipsToMm(16838) - 297) < 1)
  })

  it("matches known page presets", () => {
    assert.equal(matchPageFormatId(210, 297), "a4")
    assert.equal(matchPageFormatId(216, 279), "letter")
  })

  it("applies imported margins and custom size", () => {
    const layout = resolveDocumentPageLayout({
      widthMm: 210,
      heightMm: 297,
      marginsMm: { top: 25.4, right: 20, bottom: 25.4, left: 20 },
      formatId: "a4",
    })
    assert.equal(layout.format.id, "a4")
    assert.ok(layout.marginsPx.left < layout.marginsPx.top)
  })

  it("maps Word border sides to CSS", () => {
    const side = parseWordBorderSide('<w:top w:val="single" w:sz="12" w:color="FF0000"/>')
    assert.equal(side.style, "solid")
    assert.equal(side.color, "#FF0000")
    assert.ok(borderSzToPx(12) >= 1)

    const layout = bordersToLayoutCss({
      top: side,
      right: side,
      bottom: side,
      left: side,
      offsetFrom: "page",
    })
    assert.ok(layout.sheetBorderCss?.top?.includes("solid"))
    assert.equal(layout.textAreaBorderCss, undefined)
  })

  it("renders text-offset borders inside margins", () => {
    const side = parseWordBorderSide('<w:left w:val="double" w:sz="8" w:color="000000"/>')
    const layout = bordersToLayoutCss({
      top: { style: "none", widthPx: 0, color: "#000000" },
      right: { style: "none", widthPx: 0, color: "#000000" },
      bottom: { style: "none", widthPx: 0, color: "#000000" },
      left: side,
      offsetFrom: "text",
    })
    assert.ok(layout.textAreaBorderCss?.left?.includes("double"))
    assert.equal(layout.sheetBorderCss, undefined)
  })

  it("builds draft with margins in centimeters", () => {
    const draft = draftFromPageSetup(
      {
        widthMm: 210,
        heightMm: 297,
        marginsMm: { top: 20, right: 20, bottom: 20, left: 20 },
        formatId: "a4",
        orientation: "portrait",
      },
      "letter"
    )
    assert.equal(draft.formatId, "a4")
    assert.equal(draft.marginsCm.top, 2)
    assert.equal(draft.orientation, "portrait")
  })

  it("applies margins orientation and preserves imported borders", () => {
    const importedBorders = {
      top: { style: "solid" as const, widthPx: 2, color: "#000000" },
      right: { style: "solid" as const, widthPx: 2, color: "#000000" },
      bottom: { style: "solid" as const, widthPx: 2, color: "#000000" },
      left: { style: "solid" as const, widthPx: 2, color: "#000000" },
      offsetFrom: "text" as const,
    }

    const setup = buildPageSetupFromDraft(
      {
        formatId: "a4",
        orientation: "landscape",
        marginsCm: { top: 2.5, right: 2, bottom: 2.5, left: 2 },
        pageColor: "#fff8e1",
      },
      {
        widthMm: 210,
        heightMm: 297,
        marginsMm: { top: 20, right: 20, bottom: 20, left: 20 },
        formatId: "a4",
        borders: importedBorders,
      }
    )

    assert.equal(setup.widthMm, 297)
    assert.equal(setup.heightMm, 210)
    assert.equal(setup.orientation, "landscape")
    assert.equal(setup.marginsMm.top, cmToMm(2.5))
    assert.equal(setup.pageColor, "#fff8e1")
    assert.equal(setup.borders, importedBorders)
  })

  it("preserves margins when changing format from menubar", () => {
    const setup = buildPageSetupFromDraft(
      {
        formatId: "a4",
        orientation: "portrait",
        marginsCm: { top: 3, right: 2.5, bottom: 3, left: 2.5 },
        pageColor: "#ffffff",
      },
      null
    )
    const letter = buildPageSetupFromDraft(
      { ...draftFromPageSetup(setup, "a4"), formatId: "letter" },
      setup
    )
    assert.equal(letter.formatId, "letter")
    assert.equal(letter.marginsMm.left, cmToMm(2.5))
    assert.equal(mmToCm(letter.marginsMm.left), 2.5)
  })
})
