import type { DocPageSetup } from "./doc-page-setup.ts"
import { DOCS_PAGE_GAP_PX } from "./docs-page-layout-constants.ts"
import { mmToPx } from "./doc-page-setup.ts"

export type DocsPageMetrics = {
  pageWidth: number
  pageHeight: number
  margins: { top: number; right: number; bottom: number; left: number }
  headerMarginPx: number
  footerMarginPx: number
  bodyAreaHeight: number
  interPageSpacer: number
}

export function computePageMetrics(pageLayout: {
  widthPx: number
  heightPx: number
  marginsPx: { top: number; right: number; bottom: number; left: number }
  headerMarginMm?: number
  footerMarginMm?: number
  effectiveMarginsPx?: { top: number; right: number; bottom: number; left: number }
}): DocsPageMetrics {
  const margins = pageLayout.effectiveMarginsPx ?? pageLayout.marginsPx
  const headerMarginPx =
    pageLayout.headerMarginMm != null
      ? mmToPx(pageLayout.headerMarginMm)
      : pageLayout.marginsPx.top
  const footerMarginPx =
    pageLayout.footerMarginMm != null
      ? mmToPx(pageLayout.footerMarginMm)
      : pageLayout.marginsPx.bottom

  const bodyAreaHeight = pageLayout.heightPx - margins.top - margins.bottom
  const interPageSpacer =
    margins.bottom + DOCS_PAGE_GAP_PX + margins.top

  return {
    pageWidth: pageLayout.widthPx,
    pageHeight: pageLayout.heightPx,
    margins,
    headerMarginPx,
    footerMarginPx,
    bodyAreaHeight: Math.max(1, bodyAreaHeight),
    interPageSpacer,
  }
}

/** Page count from prose content height (excludes outer surface padding). */
export function computePageCount(contentHeight: number, metrics: DocsPageMetrics): number {
  if (contentHeight <= 0) return 1
  const { bodyAreaHeight, interPageSpacer } = metrics
  let remaining = contentHeight
  let pages = 1
  while (remaining > bodyAreaHeight) {
    remaining -= bodyAreaHeight
    if (remaining <= 0) break
    remaining -= interPageSpacer
    pages += 1
  }

  // Drop a trailing page that would be entirely empty (simulated height overshoot).
  while (pages > 1 && contentHeight <= computeProseMinHeight(pages - 1, metrics)) {
    pages -= 1
  }

  return pages
}

export function computeStackHeight(pageCount: number, pageHeight: number): number {
  return pageCount * pageHeight + Math.max(0, pageCount - 1) * DOCS_PAGE_GAP_PX
}

/** Minimum prose height to align with visual page stack including inter-page spacers. */
export function computeProseMinHeight(pageCount: number, metrics: DocsPageMetrics): number {
  const { bodyAreaHeight, interPageSpacer } = metrics
  return (
    pageCount * bodyAreaHeight + Math.max(0, pageCount - 1) * interPageSpacer
  )
}

export function emptyRegionDoc() {
  return { type: "doc", content: [{ type: "paragraph" }] }
}

export function pageSetupFromMetrics(
  setup: DocPageSetup | null | undefined,
  patch: Partial<DocPageSetup>
): DocPageSetup {
  return { ...(setup ?? defaultMinimalSetup()), ...patch }
}

function defaultMinimalSetup(): DocPageSetup {
  return {
    widthMm: 210,
    heightMm: 297,
    marginsMm: { top: 25.4, right: 25.4, bottom: 25.4, left: 25.4 },
  }
}
