const PRINT_CLASS = {
  ALL: "ptw-print-all",
  CURRENT: "ptw-print-current"
};

/** Minimal print rules so output is correct even before app stylesheets finish loading. */
const IFRAME_PRINT_STYLES = `
  @page {
    size: A4 portrait;
    margin: 10mm;
  }

  html,
  body {
    margin: 0;
    padding: 0;
    background: #fff !important;
    color: #000 !important;
    height: auto !important;
    max-height: none !important;
    overflow: visible !important;
  }

  .ptw-no-print,
  .ptw-print-exclude,
  video,
  .ptw-preview-media--video,
  .ptw-preview-media-interactive.ptw-print-exclude,
  .ptw-preview-media__loading {
    display: none !important;
  }

  .ptw-print-permit-meta {
    display: block !important;
    margin: 0 0 8px;
    padding: 0 0 6px;
    border-bottom: 1px solid #000;
    font-family: Arial, Helvetica, sans-serif;
  }

  .ptw-print-permit-meta__title {
    margin: 0 0 2px;
    font-size: 11pt;
    font-weight: 700;
  }

  .ptw-print-permit-meta__validity {
    margin: 0;
    font-size: 9pt;
  }

  .ptw-print-sheet {
    page-break-after: always;
    break-after: page;
  }

  .ptw-print-sheet:last-child {
    page-break-after: auto;
    break-after: auto;
  }

  .ptw-print-sheet__label {
    display: block;
    margin: 0 0 6px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 10pt;
    font-weight: 700;
  }

  body:not(.ptw-print-all) .ptw-print-sheet__label {
    display: none !important;
  }

  .ptw-doc-wrap,
  .ptw-doc-page,
  .ptw-doc-section,
  .ptw-doc-question-table-wrap,
  .ptw-signoff-block,
  .ptw-text-answers-block {
    height: auto !important;
    max-height: none !important;
    overflow: visible !important;
  }

  .ptw-doc-section,
  .ptw-audit-section,
  .ptw-doc-question-table-wrap,
  .ptw-signoff-block,
  .ptw-signoff-block__sheet,
  .ptw-text-answers-block {
    page-break-inside: avoid !important;
    break-inside: avoid-page !important;
  }

  .ptw-doc-page {
    border: none !important;
    box-shadow: none !important;
    display: flex !important;
    align-items: stretch !important;
    padding: 0 !important;
    page-break-inside: auto !important;
    break-inside: auto !important;
  }

  .ptw-doc-page__body {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    padding: 12px !important;
  }

  .ptw-doc-page__rail {
    display: block !important;
    position: static !important;
    flex: 0 0 18px !important;
    width: 18px !important;
    align-self: stretch !important;
    background: var(--ptw-job-color, #ffff00) !important;
    border: none !important;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  .ptw-doc-header {
    display: grid !important;
    grid-template-columns: 180px minmax(0, 1fr) minmax(220px, 280px) !important;
    grid-template-rows: minmax(70px, auto) !important;
    background: var(--ptw-job-color, #ffff00) !important;
  }

  .ptw-doc-header__hazard,
  .ptw-doc-header__permit,
  .ptw-doc-header__title,
  .ptw-doc-header__permit > span {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  .ptw-doc-header,
  .ptw-doc-section-title,
  .ptw-doc-warning,
  .ptw-doc-sheet-footer,
  .ptw-doc-sheet-footer__stripe {
    page-break-inside: avoid;
    break-inside: avoid;
    page-break-after: avoid;
    break-after: avoid-page;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  .ptw-doc-section-title {
    background: var(--ptw-job-color, #ffff00) !important;
    color: #000 !important;
    border-color: #000 !important;
  }

  .ptw-doc-sheet-footer {
    display: block !important;
  }

  .ptw-doc-question-table thead {
    display: table-header-group;
  }

  .ptw-doc-question-table,
  .ptw-signoff-block__table {
    page-break-inside: avoid !important;
    break-inside: avoid-page !important;
  }

  .ptw-doc-question-table tr,
  .ptw-signoff-block__table tr,
  .ptw-text-answers-block__item {
    page-break-inside: avoid;
    break-inside: avoid;
  }

  .ptw-doc-question-table__question {
    white-space: normal !important;
  }

  .ptw-print-media {
    max-height: none !important;
    page-break-inside: avoid;
    break-inside: avoid;
  }

  .ptw-preview-value,
  .ptw-doc-check-cell--readonly {
    border-color: #000 !important;
    background: #fff !important;
    color: #000 !important;
  }

  .ptw-doc-question-table th,
  .ptw-doc-question-table td,
  .ptw-signoff-block__table th,
  .ptw-signoff-block__table td {
    border-color: #000 !important;
    color: #000 !important;
  }

  .ptw-doc-section:has(.ptw-risk-section) {
    page-break-inside: auto !important;
    break-inside: auto !important;
  }

  .ptw-risk-section__toolbar {
    display: none !important;
  }

  .ptw-risk-section__table-wrap {
    overflow: visible !important;
    max-width: 100% !important;
  }

  .ptw-risk-section__table {
    width: 100% !important;
    min-width: 0 !important;
    max-width: 100% !important;
    table-layout: fixed !important;
  }

  .ptw-risk-section__table .ptw-doc-job-table__label,
  .ptw-risk-section__head {
    width: auto !important;
    min-width: 0 !important;
    white-space: normal !important;
    word-break: break-word;
    overflow-wrap: anywhere;
    font-size: 7pt !important;
    padding: 2px 3px !important;
    line-height: 1.2 !important;
  }

  .ptw-risk-section__table td,
  .ptw-risk-section__table th {
    white-space: normal !important;
    word-break: break-word;
    overflow-wrap: anywhere;
    padding: 3px !important;
    border-color: #000 !important;
    color: #000 !important;
  }

  .ptw-risk-section--preview .ptw-preview-value {
    min-height: 0 !important;
    font-size: 8pt !important;
    word-break: break-word;
    overflow-wrap: anywhere;
  }

  .ptw-risk-section__table tr {
    page-break-inside: avoid;
    break-inside: avoid;
  }
`;

function resolvePrintSource(scope) {
  if (scope === "all") {
    return document.querySelector(".ptw-print-all-stack");
  }
  return document.querySelector(".ptw-print-current-sheet");
}

function waitForImages(root) {
  if (!root) return Promise.resolve();
  const images = Array.from(root.querySelectorAll("img"));
  if (!images.length) return Promise.resolve();

  return Promise.all(
    images.map(
      (img) =>
        new Promise((resolve) => {
          if (img.complete && img.naturalWidth > 0) {
            resolve();
            return;
          }
          const done = () => resolve();
          img.addEventListener("load", done, { once: true });
          img.addEventListener("error", done, { once: true });
        })
    )
  );
}

function waitForStylesheets(doc) {
  const links = Array.from(doc.querySelectorAll('link[rel="stylesheet"]'));
  if (!links.length) return Promise.resolve();

  return Promise.all(
    links.map(
      (link) =>
        new Promise((resolve) => {
          if (link.sheet) {
            resolve();
            return;
          }
          link.addEventListener("load", () => resolve(), { once: true });
          link.addEventListener("error", () => resolve(), { once: true });
        })
    )
  );
}

function copyStylesToDocument(targetDoc) {
  document.querySelectorAll('link[rel="stylesheet"]').forEach((link) => {
    const clone = targetDoc.createElement("link");
    clone.rel = "stylesheet";
    clone.href = link.href;
    targetDoc.head.appendChild(clone);
  });

  document.querySelectorAll("style").forEach((style) => {
    targetDoc.head.appendChild(style.cloneNode(true));
  });
}

function createPrintIframe() {
  const iframe = document.createElement("iframe");
  iframe.setAttribute("aria-hidden", "true");
  iframe.setAttribute("title", "Permit print preview");
  iframe.style.cssText =
    "position:fixed;right:0;bottom:0;width:0;height:0;border:0;visibility:hidden;";
  document.body.appendChild(iframe);
  return iframe;
}

/**
 * Print submitted permit forms in an isolated iframe so the full document
 * prints (not just the visible scrollport of the admin shell).
 * @param {"current" | "all"} scope
 */
export async function printPermitForms(scope = "current") {
  const source = resolvePrintSource(scope);
  if (!source) {
    throw new Error("Nothing to print. Open a submitted form first.");
  }

  await waitForImages(source);

  const printMeta = document.querySelector(".ptw-print-permit-meta");
  const iframe = createPrintIframe();
  const doc = iframe.contentDocument;
  const win = iframe.contentWindow;

  if (!doc || !win) {
    iframe.remove();
    throw new Error("Could not open print preview.");
  }

  doc.open();
  doc.write(
    '<!DOCTYPE html><html><head><meta charset="utf-8"><title>Permit to Work</title></head><body></body></html>'
  );
  doc.close();

  const inlineStyles = doc.createElement("style");
  inlineStyles.textContent = IFRAME_PRINT_STYLES;
  doc.head.appendChild(inlineStyles);
  copyStylesToDocument(doc);

  doc.body.className = scope === "all" ? PRINT_CLASS.ALL : PRINT_CLASS.CURRENT;

  if (printMeta) {
    const metaClone = printMeta.cloneNode(true);
    metaClone.removeAttribute("aria-hidden");
    metaClone.style.display = "block";
    doc.body.appendChild(metaClone);
  }

  const contentClone = source.cloneNode(true);
  contentClone.removeAttribute("aria-hidden");
  doc.body.appendChild(contentClone);

  try {
    await waitForStylesheets(doc);
    await waitForImages(doc.body);
    await new Promise((resolve) => setTimeout(resolve, 150));
    win.focus();
    win.print();
  } catch (err) {
    iframe.remove();
    throw err;
  } finally {
    const cleanup = () => {
      iframe.remove();
      win.removeEventListener("afterprint", cleanup);
    };
    win.addEventListener("afterprint", cleanup, { once: true });
    window.setTimeout(() => {
      if (iframe.parentNode) iframe.remove();
    }, 120000);
  }
}
