import * as React from 'react';
import { Text, View } from '@react-pdf/renderer';

import type { DatasheetVoltageTable } from '../../model/types';
import { styles } from '../styles';

function clamp(n: number, min: number, max: number): number {
  return Math.max(min, Math.min(max, n));
}

export function DenseTable(props: {
  table: Pick<DatasheetVoltageTable, 'columns' | 'rows'>;
  firstColLabel: string;
}): React.ReactElement {
  const cols = props.table.columns;
  const rows = props.table.rows;

  const noWrapHeader = (label: string): string => {
    const raw = String(label || '').trim();
    if (!raw) return '';

    // Ensure the header never wraps into a second line.
    // - Remove whitespace break opportunities (NBSP)
    // NOTE: Avoid inserting zero-width joiners between letters.
    // Some PDF viewers render them with spacing/odd glyph behavior.
    // This is intentionally aggressive because broken headers destroy scanability.
    return raw.replace(/\s+/g, '\u00A0');
  };

  // Column widths: use explicit percentages (no rounding gaps) so the table always
  // consumes the full content width.
  // Goal:
  // - keep the designation column *not too wide*
  // - guarantee enough width for data headers when there is available space
  const cfgMin = 0.18;
  const cfgMax = 0.30;

  let cfgPct = cols.length >= 14 ? 0.22 : cols.length >= 12 ? 0.24 : cols.length >= 10 ? 0.26 : 0.30;
  cfgPct = clamp(cfgPct, cfgMin, cfgMax);

  const minDataPct = cols.length >= 14 ? 0.045 : cols.length >= 12 ? 0.05 : cols.length >= 10 ? 0.055 : 0.06;
  // If the initial cfgPct leaves too little width per data column, reduce cfgPct.
  const cfgPctMaxForMinData = 1 - cols.length * minDataPct;
  if (Number.isFinite(cfgPctMaxForMinData)) {
    cfgPct = Math.min(cfgPct, cfgPctMaxForMinData);
    cfgPct = clamp(cfgPct, cfgMin, cfgMax);
  }

  const cfgW = `${(cfgPct * 100).toFixed(4)}%`;
  const dataTotal = 1 - cfgPct;
  const each = cols.length ? dataTotal / cols.length : dataTotal;
  const dataWs = cols.map((_, idx) => {
    // Keep the last column as the remainder so percentages sum to exactly 100%.
    if (idx === cols.length - 1) {
      const used = each * Math.max(0, cols.length - 1);
      const remainder = Math.max(0, dataTotal - used);
      return `${(remainder * 100).toFixed(4)}%`;
    }
    return `${(each * 100).toFixed(4)}%`;
  });

  return (
    <View style={styles.tableWrap}>
      <View style={styles.tableHeader} wrap={false}>
        <View style={{ width: cfgW }}>
          <Text
            style={[
              styles.tableHeaderCell,
              styles.tableHeaderCellCfg,
              cols.length ? styles.tableHeaderCellDivider : null,
            ]}
            wrap={false}
          >
            {noWrapHeader(props.firstColLabel)}
          </Text>
        </View>
        {cols.map((c, idx) => {
          const isLast = idx === cols.length - 1;
          return (
            <View key={c.key} style={{ width: dataWs[idx] }}>
              <Text
                style={[styles.tableHeaderCell, !isLast ? styles.tableHeaderCellDivider : null]}
                wrap={false}
              >
                {noWrapHeader(c.label)}
              </Text>
            </View>
          );
        })}
      </View>

      {rows.map((r, ri) => (
        <View
          key={`${r.configuration}-${ri}`}
          style={[styles.tableRow, ri % 2 === 0 ? styles.tableRowAlt : null]}
          wrap={false}
        >
          <View style={{ width: cfgW }}>
            <Text style={[styles.tableCell, styles.tableCellCfg, cols.length ? styles.tableCellDivider : null]}>{r.configuration}</Text>
          </View>
          {r.cells.map((cell, ci) => {
            const isLast = ci === r.cells.length - 1;
            return (
              <View key={`${cols[ci]?.key || ci}`} style={{ width: dataWs[ci] }}>
                <Text style={[styles.tableCell, !isLast ? styles.tableCellDivider : null]}>{cell}</Text>
              </View>
            );
          })}
        </View>
      ))}
    </View>
  );
}
