/**
 * Section Properties Serializer - Serialize w:sectPr
 *
 * Converts SectionProperties back to OOXML `<w:sectPr>`. Used both for the
 * final `w:body/w:sectPr` (last section) and for mid-body section breaks
 * carried on a paragraph via `w:pPr/w:sectPr`.
 *
 * OOXML Reference:
 * - Section properties: w:sectPr (ECMA-376 §17.6.17)
 * - A paragraph-level sectPr (`w:pPr/w:sectPr`) marks the end of a section;
 *   the trailing `w:body/w:sectPr` describes the final section.
 */

import type {
  SectionProperties,
  HeaderReference,
  FooterReference,
  FootnoteProperties,
  EndnoteProperties,
  BorderSpec,
} from '../../types/document';

import { intAttr } from './xmlUtils';

/**
 * Serialize a border element
 */
function serializeBorder(border: BorderSpec | undefined, elementName: string): string {
  if (!border || border.style === 'none' || border.style === 'nil') {
    return '';
  }

  const attrs: string[] = [`w:val="${border.style}"`];

  if (border.size !== undefined) {
    attrs.push(`w:sz="${intAttr(border.size)}"`);
  }

  if (border.space !== undefined) {
    attrs.push(`w:space="${intAttr(border.space)}"`);
  }

  if (border.color) {
    if (border.color.auto) {
      attrs.push('w:color="auto"');
    } else if (border.color.rgb) {
      attrs.push(`w:color="${border.color.rgb}"`);
    }

    if (border.color.themeColor) {
      attrs.push(`w:themeColor="${border.color.themeColor}"`);
    }

    if (border.color.themeTint) {
      attrs.push(`w:themeTint="${border.color.themeTint}"`);
    }

    if (border.color.themeShade) {
      attrs.push(`w:themeShade="${border.color.themeShade}"`);
    }
  }

  if (border.shadow) {
    attrs.push('w:shadow="true"');
  }

  if (border.frame) {
    attrs.push('w:frame="true"');
  }

  return `<w:${elementName} ${attrs.join(' ')}/>`;
}

/**
 * Serialize header reference (w:headerReference)
 */
function serializeHeaderReference(ref: HeaderReference): string {
  const attrs: string[] = [`w:type="${ref.type}"`, `r:id="${ref.rId}"`];

  return `<w:headerReference ${attrs.join(' ')}/>`;
}

/**
 * Serialize footer reference (w:footerReference)
 */
function serializeFooterReference(ref: FooterReference): string {
  const attrs: string[] = [`w:type="${ref.type}"`, `r:id="${ref.rId}"`];

  return `<w:footerReference ${attrs.join(' ')}/>`;
}

/**
 * Serialize footnote properties (w:footnotePr)
 */
function serializeFootnoteProperties(props: FootnoteProperties | undefined): string {
  if (!props) return '';

  const parts: string[] = [];

  if (props.position) {
    parts.push(`<w:pos w:val="${props.position}"/>`);
  }

  if (props.numFmt) {
    parts.push(`<w:numFmt w:val="${props.numFmt}"/>`);
  }

  if (props.numStart !== undefined) {
    parts.push(`<w:numStart w:val="${props.numStart}"/>`);
  }

  if (props.numRestart) {
    parts.push(`<w:numRestart w:val="${props.numRestart}"/>`);
  }

  if (parts.length === 0) return '';

  return `<w:footnotePr>${parts.join('')}</w:footnotePr>`;
}

/**
 * Serialize endnote properties (w:endnotePr)
 */
function serializeEndnoteProperties(props: EndnoteProperties | undefined): string {
  if (!props) return '';

  const parts: string[] = [];

  if (props.position) {
    parts.push(`<w:pos w:val="${props.position}"/>`);
  }

  if (props.numFmt) {
    parts.push(`<w:numFmt w:val="${props.numFmt}"/>`);
  }

  if (props.numStart !== undefined) {
    parts.push(`<w:numStart w:val="${props.numStart}"/>`);
  }

  if (props.numRestart) {
    parts.push(`<w:numRestart w:val="${props.numRestart}"/>`);
  }

  if (parts.length === 0) return '';

  return `<w:endnotePr>${parts.join('')}</w:endnotePr>`;
}

/**
 * Serialize page size (w:pgSz)
 */
function serializePageSize(props: SectionProperties): string {
  const attrs: string[] = [];

  if (props.pageWidth !== undefined) {
    attrs.push(`w:w="${intAttr(props.pageWidth)}"`);
  }

  if (props.pageHeight !== undefined) {
    attrs.push(`w:h="${intAttr(props.pageHeight)}"`);
  }

  if (props.orientation === 'landscape') {
    attrs.push('w:orient="landscape"');
  }

  if (attrs.length === 0) return '';

  return `<w:pgSz ${attrs.join(' ')}/>`;
}

/**
 * Serialize page margins (w:pgMar)
 */
function serializePageMargins(props: SectionProperties): string {
  const attrs: string[] = [];

  if (props.marginTop !== undefined) {
    attrs.push(`w:top="${intAttr(props.marginTop)}"`);
  }

  if (props.marginRight !== undefined) {
    attrs.push(`w:right="${intAttr(props.marginRight)}"`);
  }

  if (props.marginBottom !== undefined) {
    attrs.push(`w:bottom="${intAttr(props.marginBottom)}"`);
  }

  if (props.marginLeft !== undefined) {
    attrs.push(`w:left="${intAttr(props.marginLeft)}"`);
  }

  if (props.headerDistance !== undefined) {
    attrs.push(`w:header="${intAttr(props.headerDistance)}"`);
  }

  if (props.footerDistance !== undefined) {
    attrs.push(`w:footer="${intAttr(props.footerDistance)}"`);
  }

  if (props.gutter !== undefined) {
    attrs.push(`w:gutter="${intAttr(props.gutter)}"`);
  }

  if (attrs.length === 0) return '';

  return `<w:pgMar ${attrs.join(' ')}/>`;
}

/**
 * Serialize columns (w:cols)
 */
function serializeColumns(props: SectionProperties): string {
  if (!props.columnCount && !props.columns?.length) return '';

  const attrs: string[] = [];

  if (props.columnCount !== undefined && props.columnCount > 1) {
    attrs.push(`w:num="${intAttr(props.columnCount)}"`);
  }

  if (props.columnSpace !== undefined) {
    attrs.push(`w:space="${intAttr(props.columnSpace)}"`);
  }

  if (props.equalWidth !== undefined) {
    attrs.push(`w:equalWidth="${props.equalWidth ? '1' : '0'}"`);
  }

  if (props.separator) {
    attrs.push('w:sep="1"');
  }

  // Individual column definitions
  let colElements = '';
  if (props.columns && props.columns.length > 0) {
    colElements = props.columns
      .map((col) => {
        const colAttrs: string[] = [];
        if (col.width !== undefined) {
          colAttrs.push(`w:w="${intAttr(col.width)}"`);
        }
        if (col.space !== undefined) {
          colAttrs.push(`w:space="${intAttr(col.space)}"`);
        }
        return `<w:col ${colAttrs.join(' ')}/>`;
      })
      .join('');
  }

  if (attrs.length === 0 && !colElements) return '';

  const attrsStr = attrs.length > 0 ? ' ' + attrs.join(' ') : '';
  return `<w:cols${attrsStr}>${colElements}</w:cols>`;
}

/**
 * Serialize line numbers (w:lnNumType)
 */
function serializeLineNumbers(props: SectionProperties): string {
  if (!props.lineNumbers) return '';

  const ln = props.lineNumbers;
  const attrs: string[] = [];

  if (ln.countBy !== undefined) {
    attrs.push(`w:countBy="${intAttr(ln.countBy)}"`);
  }

  if (ln.start !== undefined) {
    attrs.push(`w:start="${intAttr(ln.start)}"`);
  }

  if (ln.distance !== undefined) {
    attrs.push(`w:distance="${intAttr(ln.distance)}"`);
  }

  if (ln.restart) {
    attrs.push(`w:restart="${ln.restart}"`);
  }

  if (attrs.length === 0) return '';

  return `<w:lnNumType ${attrs.join(' ')}/>`;
}

/**
 * Serialize page borders (w:pgBorders)
 */
function serializePageBorders(props: SectionProperties): string {
  if (!props.pageBorders) return '';

  const pb = props.pageBorders;
  const attrs: string[] = [];
  const borderElements: string[] = [];

  if (pb.display) {
    attrs.push(`w:display="${pb.display}"`);
  }

  if (pb.offsetFrom) {
    attrs.push(`w:offsetFrom="${pb.offsetFrom}"`);
  }

  if (pb.zOrder) {
    attrs.push(`w:zOrder="${pb.zOrder}"`);
  }

  if (pb.top) {
    const topXml = serializeBorder(pb.top, 'top');
    if (topXml) borderElements.push(topXml);
  }

  if (pb.left) {
    const leftXml = serializeBorder(pb.left, 'left');
    if (leftXml) borderElements.push(leftXml);
  }

  if (pb.bottom) {
    const bottomXml = serializeBorder(pb.bottom, 'bottom');
    if (bottomXml) borderElements.push(bottomXml);
  }

  if (pb.right) {
    const rightXml = serializeBorder(pb.right, 'right');
    if (rightXml) borderElements.push(rightXml);
  }

  if (borderElements.length === 0) return '';

  const attrsStr = attrs.length > 0 ? ' ' + attrs.join(' ') : '';
  return `<w:pgBorders${attrsStr}>${borderElements.join('')}</w:pgBorders>`;
}

/**
 * Serialize document grid (w:docGrid)
 */
function serializeDocGrid(props: SectionProperties): string {
  if (!props.docGrid) return '';

  const dg = props.docGrid;
  const attrs: string[] = [];

  if (dg.type) {
    attrs.push(`w:type="${dg.type}"`);
  }

  if (dg.linePitch !== undefined) {
    attrs.push(`w:linePitch="${dg.linePitch}"`);
  }

  if (dg.charSpace !== undefined) {
    attrs.push(`w:charSpace="${dg.charSpace}"`);
  }

  if (attrs.length === 0) return '';

  return `<w:docGrid ${attrs.join(' ')}/>`;
}

/**
 * Serialize section properties (w:sectPr)
 */
export function serializeSectionProperties(props: SectionProperties | undefined): string {
  if (!props) return '';

  const parts: string[] = [];

  // Header references
  if (props.headerReferences) {
    for (const ref of props.headerReferences) {
      parts.push(serializeHeaderReference(ref));
    }
  }

  // Footer references
  if (props.footerReferences) {
    for (const ref of props.footerReferences) {
      parts.push(serializeFooterReference(ref));
    }
  }

  // Footnote properties
  const footnotePrXml = serializeFootnoteProperties(props.footnotePr);
  if (footnotePrXml) {
    parts.push(footnotePrXml);
  }

  // Endnote properties
  const endnotePrXml = serializeEndnoteProperties(props.endnotePr);
  if (endnotePrXml) {
    parts.push(endnotePrXml);
  }

  // Section type
  if (props.sectionStart) {
    parts.push(`<w:type w:val="${props.sectionStart}"/>`);
  }

  // Page size
  const pgSzXml = serializePageSize(props);
  if (pgSzXml) {
    parts.push(pgSzXml);
  }

  // Page margins
  const pgMarXml = serializePageMargins(props);
  if (pgMarXml) {
    parts.push(pgMarXml);
  }

  // Paper source
  if (props.paperSrcFirst !== undefined || props.paperSrcOther !== undefined) {
    const attrs: string[] = [];
    if (props.paperSrcFirst !== undefined) {
      attrs.push(`w:first="${props.paperSrcFirst}"`);
    }
    if (props.paperSrcOther !== undefined) {
      attrs.push(`w:other="${props.paperSrcOther}"`);
    }
    parts.push(`<w:paperSrc ${attrs.join(' ')}/>`);
  }

  // Page borders
  const pgBordersXml = serializePageBorders(props);
  if (pgBordersXml) {
    parts.push(pgBordersXml);
  }

  // Line numbers
  const lnNumXml = serializeLineNumbers(props);
  if (lnNumXml) {
    parts.push(lnNumXml);
  }

  // Columns
  const colsXml = serializeColumns(props);
  if (colsXml) {
    parts.push(colsXml);
  }

  // Remaining EG_SectPrContents elements MUST follow schema order
  // (wml.xsd CT_SectPr): ... cols, vAlign, titlePg, bidi, docGrid. Emitting
  // docGrid early or bidi before titlePg makes strict OOXML validators reject
  // the file (Word itself is lenient and reorders on open).

  // Vertical alignment
  if (props.verticalAlign) {
    parts.push(`<w:vAlign w:val="${props.verticalAlign}"/>`);
  }

  // Title page (different first page header/footer)
  if (props.titlePg) {
    parts.push('<w:titlePg/>');
  }

  // Bidirectional
  if (props.bidi) {
    parts.push('<w:bidi/>');
  }

  // Document grid (last EG_SectPrContents element this serializer emits)
  const docGridXml = serializeDocGrid(props);
  if (docGridXml) {
    parts.push(docGridXml);
  }

  // Even and odd headers. NOTE: this is a CT_Settings element (settings.xml),
  // not a CT_SectPr child; it is emitted here only to round-trip non-standard
  // input that carried it inside `w:sectPr` (the parser reads it from there).
  // Real Word documents store it in settings.xml, so this branch is inert for
  // them. Kept last to avoid disturbing the schema-ordered elements above.
  if (props.evenAndOddHeaders) {
    parts.push('<w:evenAndOddHeaders/>');
  }

  if (parts.length === 0) return '';

  return `<w:sectPr>${parts.join('')}</w:sectPr>`;
}
