import React from 'react';

interface StatementMetric<Row> {
  key: string;
  label: string;
  render: (period: Row) => React.ReactNode;
  mappable?: boolean;
}

interface MappingCellInfo {
  metricKey: string;
  metricLabel: string;
  periodLabel: string;
}

interface StatementTableMinimalProps<Row extends { label: string }> {
  periods: Row[];
  metrics: StatementMetric<Row>[];
  /** Enable inline mapping customizer for missing values */
  enableMappingCustomizer?: boolean;
  /** Callback when user clicks "Map" on a missing value cell */
  onMapField?: (cellInfo: MappingCellInfo) => void;
}

const numericFormatter = new Intl.NumberFormat('en-US', {
  maximumFractionDigits: 2,
});

const isMissingNumber = (value: number | null | undefined): value is null | undefined =>
  value === null || value === undefined || Number.isNaN(value);

export const formatMoney = (value?: number | null) => {
  if (isMissingNumber(value)) return '—';
  if (Math.abs(value) >= 1e12) return `$${(value / 1e12).toFixed(2)}T`;
  if (Math.abs(value) >= 1e9) return `$${(value / 1e9).toFixed(2)}B`;
  if (Math.abs(value) >= 1e6) return `$${(value / 1e6).toFixed(2)}M`;
  return `$${numericFormatter.format(value)}`;
};

export const formatNumber = (value?: number | null) =>
  isMissingNumber(value) ? '—' : numericFormatter.format(value);

export const formatPercent = (value?: number | null) =>
  isMissingNumber(value) ? '—' : `${value >= 0 ? '+' : ''}${value.toFixed(1)}%`;

/**
 * Check if a rendered value represents a missing/empty value.
 */
function isMissingValue(value: React.ReactNode): boolean {
  if (value === null || value === undefined) {
    return true;
  }
  if (typeof value === 'string' && value.trim() === '—') {
    return true;
  }
  return false;
}

/**
 * Render a cell with optional mapping customizer button.
 */
function renderCell<Row extends { label: string }>(
  metric: StatementMetric<Row>,
  period: Row,
  enableMappingCustomizer: boolean,
  onMapField?: (cellInfo: MappingCellInfo) => void
): React.ReactNode {
  const value = metric.render(period);
  const missing =
    enableMappingCustomizer && Boolean(metric.mappable) && isMissingValue(value);

  if (!missing) {
    return <span className="inline-block">{value}</span>;
  }

  const cellInfo: MappingCellInfo = {
    metricKey: metric.key,
    metricLabel: metric.label,
    periodLabel: period.label,
  };

  return (
    <div className="group relative inline-flex items-center justify-end gap-2">
      <span className="text-term-text-tertiary">{value}</span>
      <button
        onClick={() => onMapField?.(cellInfo)}
        className="rounded border border-term-border-subtle bg-term-bg-secondary px-2 py-0.5 text-[10px] font-medium text-term-text-muted opacity-0 transition-opacity group-hover:opacity-100 hover:border-term-border hover:bg-term-bg-tertiary hover:text-term-text"
        title="Create a custom mapping for this field"
      >
        Map
      </button>
    </div>
  );
}

export function StatementTableMinimal<Row extends { label: string }>({
  periods,
  metrics,
  enableMappingCustomizer = false,
  onMapField,
}: StatementTableMinimalProps<Row>) {
  return (
    <div className="overflow-x-auto">
      <table className="min-w-full border-collapse font-mono text-sm">
        <thead className="text-term-text-muted">
          <tr className="border-b border-term-border-subtle">
            <th className="sticky left-0 border-r border-term-border-subtle bg-term-bg px-3 py-2 text-left text-[10px] uppercase tracking-[0.18em]">
              Item
            </th>
            {periods.map((period) => (
              <th
                key={period.label}
                className="border-b border-term-border-subtle px-3 py-2 text-right text-[10px] uppercase tracking-[0.18em]"
              >
                {period.label}
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {metrics.map((metric) => (
            <tr key={metric.key} className="border-b border-term-border-subtle last:border-b-0">
              <th className="sticky left-0 border-r border-term-border-subtle bg-term-bg px-3 py-2 text-left font-medium text-term-text">
                {metric.label}
              </th>
              {periods.map((period) => (
                <td key={`${metric.key}-${period.label}`} className="px-3 py-2 text-right text-term-text">
                  {renderCell(metric, period, enableMappingCustomizer, onMapField)}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}
