import { StyleSheet, Text, View } from '@react-pdf/renderer';
import type { ReactNode } from 'react';

import { PDF_TOKENS } from './tokens';

const styles = StyleSheet.create({
  wrap: {
    flexDirection: 'column',
    borderTopWidth: 1,
    borderTopColor: PDF_TOKENS.colors.border,
  },
  headerRow: {
    flexDirection: 'row',
    backgroundColor: PDF_TOKENS.colors.headerBand,
    paddingVertical: 6,
    paddingHorizontal: 8,
  },
  bodyRow: {
    flexDirection: 'row',
    paddingVertical: 6,
    paddingHorizontal: 8,
    borderBottomWidth: 1,
    borderBottomColor: PDF_TOKENS.colors.border,
  },
  zebraRow: {
    backgroundColor: PDF_TOKENS.colors.zebra,
  },
  totalsRow: {
    flexDirection: 'row',
    paddingVertical: 6,
    paddingHorizontal: 8,
    borderTopWidth: 1,
    borderTopColor: PDF_TOKENS.colors.text,
    borderBottomWidth: 1,
    borderBottomColor: PDF_TOKENS.colors.text,
  },
  headerCell: {
    fontFamily: PDF_TOKENS.fonts.sansBold,
    fontSize: PDF_TOKENS.sizes.small,
    color: PDF_TOKENS.colors.headerText,
    textTransform: 'uppercase',
    letterSpacing: 0.4,
  },
  bodyCell: {
    fontFamily: PDF_TOKENS.fonts.sans,
    fontSize: PDF_TOKENS.sizes.body,
    color: PDF_TOKENS.colors.text,
  },
  bodyCellMuted: {
    fontFamily: PDF_TOKENS.fonts.sans,
    fontSize: PDF_TOKENS.sizes.small,
    color: PDF_TOKENS.colors.textMuted,
  },
  totalsCell: {
    fontFamily: PDF_TOKENS.fonts.sansBold,
    fontSize: PDF_TOKENS.sizes.body,
    color: PDF_TOKENS.colors.text,
  },
});

export type Align = 'left' | 'right' | 'center';

export interface TableColumn<Row> {
  header: string;
  /** grow weight (default 1) - controls column width proportions. */
  flex?: number;
  align?: Align;
  render: (row: Row, rowIndex: number) => ReactNode;
}

export interface DataTableProps<Row> {
  columns: TableColumn<Row>[];
  rows: Row[];
  /** Render a bold totals row beneath the body. Cell value-or-null per column. */
  totals?: (string | null)[];
  /** Apply zebra background to alternate rows (default true). */
  zebra?: boolean;
  /** Empty-state text shown when rows.length === 0. */
  emptyMessage?: string;
}

function cellStyle(align: Align | undefined, base: Record<string, unknown>) {
  return {
    flex: 1,
    paddingHorizontal: 4,
    textAlign: align ?? 'left',
    ...base,
  } as const;
}

export function DataTable<Row>({
  columns,
  rows,
  totals,
  zebra = true,
  emptyMessage = 'No entries',
}: DataTableProps<Row>) {
  return (
    <View style={styles.wrap}>
      <View style={styles.headerRow} fixed>
        {columns.map((c, i) => (
          <Text
            key={i}
            style={{
              flex: c.flex ?? 1,
              paddingHorizontal: 4,
              textAlign: c.align ?? 'left',
              ...styles.headerCell,
            }}
          >
            {c.header}
          </Text>
        ))}
      </View>
      {rows.length === 0 ? (
        <View style={styles.bodyRow}>
          <Text style={{ ...styles.bodyCellMuted, flex: 1, textAlign: 'center' }}>
            {emptyMessage}
          </Text>
        </View>
      ) : (
        rows.map((row, i) => (
          <View
            key={i}
            style={[styles.bodyRow, zebra && i % 2 === 1 ? styles.zebraRow : {}]}
            wrap={false}
          >
            {columns.map((c, ci) => (
              <View
                key={ci}
                style={{
                  flex: c.flex ?? 1,
                  paddingHorizontal: 4,
                  alignItems:
                    c.align === 'right'
                      ? 'flex-end'
                      : c.align === 'center'
                        ? 'center'
                        : 'flex-start',
                }}
              >
                {(() => {
                  const node = c.render(row, i);
                  if (typeof node === 'string' || typeof node === 'number') {
                    return <Text style={styles.bodyCell}>{node}</Text>;
                  }
                  return node;
                })()}
              </View>
            ))}
          </View>
        ))
      )}
      {totals ? (
        <View style={styles.totalsRow}>
          {columns.map((c, i) => (
            <Text key={i} style={cellStyle(c.align, styles.totalsCell)}>
              {totals[i] ?? ''}
            </Text>
          ))}
        </View>
      ) : null}
    </View>
  );
}
