import type { Handler } from './types.js';
import { fileError, type GenericNode } from 'myst-common';

function countColumns(table: GenericNode) {
  const firstRow = table.children?.find((child) => child.type === 'tableRow');
  const columns = firstRow?.children
    ?.filter((cell: GenericNode) => cell.type === 'tableCell')
    .reduce((val: number, cell: GenericNode) => val + (cell.colspan ?? 1), 0);
  return columns;
}

function isHeaderRow(node: GenericNode) {
  if (node.type !== 'tableRow') return false;
  return node.children
    ?.filter((child) => child.type === 'tableCell')
    .every((child) => child.header);
}

function countHeaderRows(table: GenericNode) {
  const headerRows = table.children?.filter((child) => isHeaderRow(child));
  return headerRows?.length ?? 0;
}

export const tableHandler: Handler = (node, state) => {
  const prevState = state.data.isInTable;
  state.data.isInTable = true;
  const command = state.data.isInFigure ? 'tablex' : '#tablex';
  const columns = countColumns(node);
  if (!columns) {
    fileError(state.file, 'Unable to count table columns', {
      node,
      source: 'myst-to-typst',
    });
    return;
  }
  state.useMacro('#import "@preview/tablex:0.0.9": tablex, cellx, hlinex, vlinex');
  // These two separate style hooks are somewhat redundant, but they allow defining
  // article-wide styles and single-table styles separately
  state.useMacro('#let tableStyle = (:)');
  state.useMacro('#let columnStyle = (:)');
  state.write(
    `${command}(columns: ${columns}, header-rows: ${countHeaderRows(node)}, repeat-header: true, ..tableStyle, ..columnStyle,\n`,
  );
  state.renderChildren(node, 1);
  state.write(')\n');
  state.data.isInTable = prevState;
};

export const tableRowHandler: Handler = (node, state) => {
  state.renderChildren(node, 1);
};

export const tableCellHandler: Handler = (node, state) => {
  if (node.rowspan || node.colspan || node.align || node.style?.backgroundColor) {
    state.write('cellx(');
    if (node.rowspan) {
      state.write(`rowspan: ${node.rowspan}, `);
    }
    if (node.colspan) {
      state.write(`colspan: ${node.colspan}, `);
    }
    if (node.align) {
      state.write(`align: ${node.align}, `);
    }
    if (node.style?.backgroundColor) {
      const fill = node.style.backgroundColor as string;
      const rgb = fill.startsWith('#');
      state.write(`fill: ${rgb ? `rgb("${fill}")` : fill}, `);
    }
    state.write(')');
  }
  state.write('[\n');
  state.renderChildren(node, 1);
  state.write('],\n');
};
