import type { DocPageHeaderFooter, DocPageLayout, DocPageSetup } from "./doc-page-setup.ts"
import { mmToPx, pxToMm } from "./doc-page-setup.ts"

export type DocsHeaderFooterRegion = "header" | "footer"

/** Height of the Google Docs–style header/footer chrome bar (px). */
export const DOCS_HF_CHROME_BAR_PX = 28

export function headerOffsetPx(pageLayout: DocPageLayout): number {
  return pageLayout.headerMarginMm != null
    ? mmToPx(pageLayout.headerMarginMm)
    : 0
}

export function footerOffsetPx(pageLayout: DocPageLayout): number {
  return pageLayout.footerMarginMm != null
    ? mmToPx(pageLayout.footerMarginMm)
    : 0
}

export function defaultHeaderZoneHeightPx(pageLayout: DocPageLayout): number {
  return Math.max(24, pageLayout.marginsPx.top - headerOffsetPx(pageLayout))
}

export function defaultFooterZoneHeightPx(pageLayout: DocPageLayout): number {
  return Math.max(24, pageLayout.marginsPx.bottom - footerOffsetPx(pageLayout))
}

export function regionZoneHeightPx(
  region: DocPageHeaderFooter | null | undefined,
  defaultPx: number
): number {
  if (region?.heightMm != null && region.heightMm > 0) {
    return Math.max(defaultPx, mmToPx(region.heightMm))
  }
  return defaultPx
}

/** Header/footer content shown on a given page index. */
export function resolveRegionForPage(
  pageLayout: DocPageLayout,
  region: DocsHeaderFooterRegion,
  pageIndex: number
): DocPageHeaderFooter | null | undefined {
  const differentFirst = pageLayout.headerFooterDifferentFirstPage ?? false
  if (region === "header") {
    if (pageIndex === 0 && differentFirst) return pageLayout.headerFirstPage ?? null
    return pageLayout.header
  }
  if (pageIndex === 0 && differentFirst) return pageLayout.footerFirstPage ?? null
  return pageLayout.footer
}

export function effectiveTopMarginPx(pageLayout: DocPageLayout): number {
  const offset = headerOffsetPx(pageLayout)
  const defaultZone = defaultHeaderZoneHeightPx(pageLayout)
  const sharedH = regionZoneHeightPx(pageLayout.header, defaultZone)
  const firstH = pageLayout.headerFooterDifferentFirstPage
    ? regionZoneHeightPx(pageLayout.headerFirstPage, defaultZone)
    : sharedH
  return Math.max(pageLayout.marginsPx.top, offset + Math.max(sharedH, firstH))
}

export function effectiveBottomMarginPx(pageLayout: DocPageLayout): number {
  const offset = footerOffsetPx(pageLayout)
  const defaultZone = defaultFooterZoneHeightPx(pageLayout)
  const sharedH = regionZoneHeightPx(pageLayout.footer, defaultZone)
  const firstH = pageLayout.headerFooterDifferentFirstPage
    ? regionZoneHeightPx(pageLayout.footerFirstPage, defaultZone)
    : sharedH
  return Math.max(pageLayout.marginsPx.bottom, offset + Math.max(sharedH, firstH))
}

export function effectiveMarginsPx(
  pageLayout: DocPageLayout,
  livePreview?: { region: DocsHeaderFooterRegion; heightPx: number } | null,
  measuredHeights?: Partial<Record<DocsHeaderFooterRegion, number>>
) {
  let top = effectiveTopMarginPx(pageLayout)
  let bottom = effectiveBottomMarginPx(pageLayout)

  if (measuredHeights?.header != null) {
    const offset = headerOffsetPx(pageLayout)
    top = Math.max(pageLayout.marginsPx.top, offset + measuredHeights.header)
  }
  if (measuredHeights?.footer != null) {
    const offset = footerOffsetPx(pageLayout)
    bottom = Math.max(pageLayout.marginsPx.bottom, offset + measuredHeights.footer)
  }

  if (livePreview) {
    const { region, heightPx } = livePreview
    if (region === "header") {
      const offset = headerOffsetPx(pageLayout)
      top = Math.max(pageLayout.marginsPx.top, offset + heightPx)
    } else {
      const offset = footerOffsetPx(pageLayout)
      bottom = Math.max(pageLayout.marginsPx.bottom, offset + heightPx)
    }
  }

  return {
    top,
    right: pageLayout.marginsPx.right,
    bottom,
    left: pageLayout.marginsPx.left,
  }
}

export function pageRegionZoneHeightPx(
  pageLayout: DocPageLayout,
  region: DocsHeaderFooterRegion,
  pageIndex: number
): number {
  const data = resolveRegionForPage(pageLayout, region, pageIndex)
  const defaultPx =
    region === "header"
      ? defaultHeaderZoneHeightPx(pageLayout)
      : defaultFooterZoneHeightPx(pageLayout)
  return regionZoneHeightPx(data, defaultPx)
}

export function pageHeaderGeometry(
  pageLayout: DocPageLayout,
  pageTop: number,
  pageIndex: number
) {
  const offset = headerOffsetPx(pageLayout)
  const zoneHeight = pageRegionZoneHeightPx(pageLayout, "header", pageIndex)
  const zoneTop = pageTop + offset
  return {
    zoneTop,
    zoneHeight,
    bottomLine: zoneTop + zoneHeight,
    offset,
  }
}

export function pageFooterGeometry(
  pageLayout: DocPageLayout,
  pageTop: number,
  pageHeight: number,
  pageIndex: number
) {
  const offset = footerOffsetPx(pageLayout)
  const zoneHeight = pageRegionZoneHeightPx(pageLayout, "footer", pageIndex)
  const zoneBottom = pageTop + pageHeight - offset
  return {
    zoneTop: zoneBottom - zoneHeight,
    zoneHeight,
    zoneBottom,
    topLine: zoneBottom - zoneHeight,
    offset,
  }
}

export function regionStorageKey(
  region: DocsHeaderFooterRegion,
  pageIndex: number,
  differentFirstPage: boolean
): keyof DocPageSetup {
  if (pageIndex === 0 && differentFirstPage) {
    return region === "header" ? "headerFirstPage" : "footerFirstPage"
  }
  return region
}

export function buildRegionPatch(
  setup: DocPageSetup,
  region: DocsHeaderFooterRegion,
  pageIndex: number,
  content: Record<string, unknown>,
  contentHeightPx: number
): Partial<DocPageSetup> {
  const differentFirst = setup.headerFooterDifferentFirstPage ?? false
  const key = regionStorageKey(region, pageIndex, differentFirst)
  const topPx = mmToPx(setup.marginsMm.top)
  const bottomPx = mmToPx(setup.marginsMm.bottom)
  const headerOff =
    setup.headerMarginMm != null ? mmToPx(setup.headerMarginMm) : 0
  const footerOff =
    setup.footerMarginMm != null ? mmToPx(setup.footerMarginMm) : 0
  const defaultZonePx =
    region === "header" ? Math.max(24, topPx - headerOff) : Math.max(24, bottomPx - footerOff)
  const heightMm = pxToMm(Math.max(defaultZonePx, contentHeightPx))
  return {
    [key]: { content, heightMm },
  }
}

export function toggleDifferentFirstPage(
  setup: DocPageSetup,
  enabled: boolean
): Partial<DocPageSetup> {
  if (enabled) {
    return {
      headerFooterDifferentFirstPage: true,
      headerFirstPage: setup.headerFirstPage ?? setup.header ?? null,
      footerFirstPage: setup.footerFirstPage ?? setup.footer ?? null,
    }
  }
  return { headerFooterDifferentFirstPage: false }
}
