import {
  Canvas,
  Controls,
  Meta,
  Story,
  Subtitle,
  Title,
} from '@storybook/addon-docs/blocks'
import * as TableStories from './DataTable.stories'
import { LifecycleTag, SourceLinks } from '../../docs/components'

<Meta of={TableStories} />

<Title>DataTable</Title>
<Subtitle>
  A powerful and flexible data table component built on TanStack Table and the
  Table primitives, with support for sorting, filtering, and pagination.
</Subtitle>
<SourceLinks
  links={[
    {
      label: 'TanStack Table',
      href: 'https://tanstack.com/table/latest',
    },
    {
      label: 'shadcn/ui',
      href: 'https://ui.shadcn.com/docs/components/data-table',
    },
  ]}
/>
<LifecycleTag variant="In Development" />

<Canvas of={TableStories.Default} sourceState="shown">
  <Controls />
</Canvas>

## Anatomy

The `DataTable` component is a high-level abstraction that handles the logic for rendering, sorting, and pagination. It is built on top of the [Table primitives](./Table.mdx) (`TableRoot`, `TableHeader`, `TableBody`, `TableRow`, `TableHead`, `TableCell`), which provide the foundational styling and structure, while TanStack Table provides the data management and interaction logic.

## Usage

### Import

```tsx
import { DataTable, type DataTableColumn } from '@chainlink/blocks'
```

### Example

```tsx
type MyDataType = {
  name: string
  age: number
}

const columns: DataTableColumn<MyDataType>[] = [
  {
    accessorKey: 'name',
    header: 'Name',
  },
  {
    accessorKey: 'age',
    header: 'Age',
  },
]

const data: MyDataType[] = [
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 },
]

export function MyTable() {
  return <DataTable columns={columns} data={data} />
}
```

## Pagination

The table supports both client-side and server-side pagination through a simple `pagination` prop. By default, it uses client-side pagination with 10 rows per page.

### Client-Side Pagination

Client-side pagination is enabled by default and works well for datasets with a few thousand rows or less.

<Canvas of={TableStories.WithPagination} sourceState="shown" />

### Custom Page Size

You can easily customize the page size using the `pagination` prop:

<Canvas of={TableStories.WithCustomPagination} sourceState="shown" />

### Select Pagination Controls

If the total count is known, pagination can render a page select automatically.

```tsx
<DataTable
  columns={columns}
  data={data}
  pagination={{
    pageSize: 3,
    pageControlMode: 'select',
  }}
/>
```

<Canvas of={TableStories.WithSelectPagination} sourceState="shown" />

### Display Pagination Controls

Use `pagination.showPaginationDisplay={false}` with
`pagination.pageControlMode="display"` when you want the static `Page N`
control without the `Showing X to Y` text.

```tsx
<DataTable
  columns={columns}
  data={data}
  pagination={{
    pageSize: 3,
    pageControlMode: 'display',
    showPaginationDisplay: false,
  }}
/>
```

<Canvas of={TableStories.WithDisplayPagination} sourceState="shown" />

### Server-Side Pagination

For large datasets, server-side pagination is recommended. This approach fetches only the data needed for the current page, reducing memory usage and improving performance.

<Canvas of={TableStories.ServerSidePagination} sourceState="shown" />

#### Server-Side Pagination Implementation

To implement server-side pagination, simply pass a `pagination` configuration:

```tsx
import { DataTable, type PaginationConfig } from '@chainlink/blocks'

const paginationConfig: PaginationConfig = {
  pageSize: 10,
  serverSide: true,
  totalCount: 150,
  onPageChange: (pageIndex, pageSize) => {
    // Fetch data for the new page
    fetchData(pageIndex, pageSize)
  },
}

<DataTable
  columns={columns}
  data={data}
  isLoading={isLoading}
  pagination={paginationConfig}
/>
```

#### Server-Side Pagination Without Total Count

If your backend returns the current page and a `has_more` flag instead of a
total count, omit `totalCount` and pass `currentPageCount` plus `canNextPage`.

<Canvas
  of={TableStories.ServerSidePaginationWithoutTotal}
  sourceState="shown"
/>

<Canvas
  of={TableStories.ServerSidePaginationWithoutTotalDisplay}
  sourceState="shown"
/>

```tsx
import { DataTable, type PaginationConfig } from '@chainlink/blocks'

const paginationConfig: PaginationConfig = {
  pageIndex,
  pageSize: 10,
  serverSide: true,
  currentPageCount: data.length,
  canNextPage: hasMore,
  onPageChange: (pageIndex, pageSize) => {
    fetchData(pageIndex, pageSize)
  },
}

<DataTable
  columns={columns}
  data={data}
  isLoading={isLoading}
  pagination={paginationConfig}
/>
```

#### Pagination Configuration Options

- `pageSize`: Number of rows per page (default: 10)
- `serverSide`: Enable server-side pagination (default: false)
- `totalCount`: Total number of records when known
- `currentPageCount`: Number of rows in the current page when `totalCount` is unknown
- `canNextPage`: Whether another page is available when `totalCount` is unknown
- `onPageChange`: Callback when page changes (required for server-side)
- `pageControlMode`: Pagination controls mode: `'select' | 'display'` (default: `'select'`)
- `showPaginationDisplay`: Whether to show the `Showing X to Y` range text (default: `true`)

## Loading

The `isLoading` prop displays skeleton loaders in each cell. The number of skeleton rows displayed follows this priority:

1. **`placeholderCount`** - if provided, always uses this value (overrides everything)
2. **`data.length`** - if data exists and has items, uses the data's length
3. **`pagination.pageSize`** - if pagination is provided and no data exists yet, uses pageSize
4. **Default: 5** - fallback when none of the above are provided

### With Existing Data

When data exists and `isLoading` is true, the table shows skeleton rows matching the data length. This is useful for refresh scenarios where you want to maintain the table height.

<Canvas of={TableStories.Loading} sourceState="shown" />

### With Pagination (No Data)

When pagination is configured but no data exists yet, the table uses `pageSize` for placeholder rows.

<Canvas
  of={TableStories.LoadingWithPlaceholdersFromPagination}
  sourceState="shown"
/>

### Default (No Data, No Pagination)

When no data, pagination, or `placeholderCount` is provided, the table shows 5 placeholder rows by default.

<Canvas of={TableStories.LoadingDefault} sourceState="shown" />

### Custom Placeholder Count (Override)

The `placeholderCount` prop overrides all other logic. Use this when you need a specific number of skeleton rows regardless of data or pagination.

<Canvas
  of={TableStories.LoadingWithCustomPlaceholderCount}
  sourceState="shown"
/>

## Examples

### Empty State

When no data is provided, the table displays a "No data available" message.

<Canvas of={TableStories.Empty} sourceState="shown" />

### Oracle Table Example

A real-world example demonstrating a more complex table with custom cell rendering.

<Canvas of={TableStories.OracleTableExample} sourceState="shown" />
