import { splitProps, mergeProps, createSignal, For, JSX } from 'solid-js';
import clsx from 'clsx';

export interface TableColumn<T = any> {
  key: string;
  header: string;
  sortable?: boolean;
  width?: string;
  render?: (value: any, row: T) => JSX.Element;
}

export interface TableProps<T = any> {
  columns: TableColumn<T>[];
  data: T[];
  onSort?: (key: string, direction: 'asc' | 'desc') => void;
  size?: 'sm' | 'md' | 'lg';
  accent?: string;
  class?: string;
}

interface SortState {
  key: string;
  direction: 'asc' | 'desc';
}

/**
 * Table -- data table with sortable columns, row hover, and minimal cyberpunk styling.
 *
 * Uses semantic <table> elements for accessibility.
 * Minimal row-based layout: no vertical column lines, subtle row dividers.
 * Header row stands out with accent color and display font.
 * Sortable columns show angular sort indicators with aria-sort.
 */
export function Table<T extends Record<string, any>>(rawProps: TableProps<T>) {
  const merged = mergeProps({ size: 'md' as const }, rawProps);
  const [local] = splitProps(merged, [
    'columns', 'data', 'onSort', 'size', 'accent', 'class',
  ]);

  const [sortState, setSortState] = createSignal<SortState | null>(null);

  // Handle sort column click
  const handleSort = (col: TableColumn<T>) => {
    if (!col.sortable) return;

    const current = sortState();
    let next: SortState | null;

    if (current?.key === col.key) {
      if (current.direction === 'asc') {
        next = { key: col.key, direction: 'desc' };
      } else {
        // Clear sort
        next = null;
      }
    } else {
      next = { key: col.key, direction: 'asc' };
    }

    setSortState(next);

    if (next && local.onSort) {
      local.onSort(next.key, next.direction);
    }
  };

  // Get sorted data (internal sorting when no onSort callback)
  const sortedData = (): T[] => {
    const sort = sortState();
    if (!sort || local.onSort) {
      // External sorting or no sort -- return data as-is
      return local.data;
    }

    // Internal sorting
    return [...local.data].sort((a, b) => {
      const aVal = a[sort.key];
      const bVal = b[sort.key];

      if (aVal == null && bVal == null) return 0;
      if (aVal == null) return sort.direction === 'asc' ? -1 : 1;
      if (bVal == null) return sort.direction === 'asc' ? 1 : -1;

      let cmp: number;
      if (typeof aVal === 'number' && typeof bVal === 'number') {
        cmp = aVal - bVal;
      } else {
        cmp = String(aVal).localeCompare(String(bVal));
      }

      return sort.direction === 'asc' ? cmp : -cmp;
    });
  };

  // Get cell value
  const getCellValue = (row: T, col: TableColumn<T>): JSX.Element => {
    const value = row[col.key];
    if (col.render) {
      return col.render(value, row);
    }
    return <>{value != null ? String(value) : ''}</>;
  };

  // Get aria-sort for a column
  const getAriaSort = (col: TableColumn<T>): 'ascending' | 'descending' | undefined => {
    const sort = sortState();
    if (!sort || sort.key !== col.key) return undefined;
    return sort.direction === 'asc' ? 'ascending' : 'descending';
  };

  const accentStyle = (): JSX.CSSProperties | undefined => {
    if (local.accent) {
      return { '--hh-comp-accent': local.accent } as JSX.CSSProperties;
    }
    return undefined;
  };

  return (
    <div
      class={clsx(
        'hh-table-wrapper',
        `hh-size-${local.size}`,
        local.class,
      )}
      style={accentStyle()}
    >
      <table class="hh-table">
        <thead>
          <tr>
            <For each={local.columns}>
              {(col) => (
                <th
                  class={clsx(
                    col.sortable && 'hh-table__th--sortable',
                    sortState()?.key === col.key && 'hh-table__th--sorted',
                  )}
                  style={col.width ? { width: col.width } : undefined}
                  aria-sort={getAriaSort(col)}
                  onClick={() => handleSort(col)}
                >
                  {col.header}
                  {col.sortable && (
                    <span
                      class={clsx(
                        'hh-table__sort-indicator',
                        sortState()?.key === col.key &&
                          sortState()?.direction === 'desc' &&
                          'hh-table__sort-indicator--desc',
                      )}
                      aria-hidden="true"
                    >
                      {'\u25B4'}
                    </span>
                  )}
                </th>
              )}
            </For>
          </tr>
        </thead>
        <tbody>
          <For each={sortedData()}>
            {(row) => (
              <tr>
                <For each={local.columns}>
                  {(col) => (
                    <td>{getCellValue(row, col)}</td>
                  )}
                </For>
              </tr>
            )}
          </For>
        </tbody>
      </table>
    </div>
  );
}
