import { useMemo, useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import type { SortState } from '../types/sort';
import { Chip } from './Chip';
import { Table, type TableHeader } from './Table';

type UserRow = {
    id: string;
    name: string;
    role: 'ADMIN' | 'EDITOR' | 'AUTHOR';
    status: 'Active' | 'Pending';
    posts: number;
};

const rows: UserRow[] = [
    { id: '1', name: 'Beatrice Rosa', role: 'ADMIN', status: 'Active', posts: 48 },
    { id: '2', name: 'Luca Valli', role: 'EDITOR', status: 'Active', posts: 26 },
    { id: '3', name: 'Marta Bellini', role: 'AUTHOR', status: 'Pending', posts: 4 },
    { id: '4', name: 'Giulia Fontana', role: 'AUTHOR', status: 'Active', posts: 12 },
    { id: '5', name: 'Andrea Pini', role: 'EDITOR', status: 'Pending', posts: 9 },
    { id: '6', name: 'Sofia Denti', role: 'AUTHOR', status: 'Active', posts: 7 },
    { id: '7', name: 'Marco Serra', role: 'AUTHOR', status: 'Active', posts: 18 },
    { id: '8', name: 'Elena Neri', role: 'EDITOR', status: 'Active', posts: 31 },
];

const headers: TableHeader<UserRow>[] = [
    {
        id: 'name',
        label: 'Name',
        value: (row) => row.name,
        sortable: true,
        sortField: 'name',
        cellClassName: 'table-cell-primary',
    },
    {
        id: 'role',
        label: 'Role',
        value: (row) => row.role,
        sortable: true,
        sortField: 'role',
    },
    {
        id: 'status',
        label: 'Status',
        value: (row) => (
            <Chip variant="outlined" tone={row.status === 'Active' ? 'indigo-700' : 'cyan-700'}>
                {row.status}
            </Chip>
        ),
    },
    {
        id: 'posts',
        label: 'Posts',
        value: (row) => row.posts,
        sortable: true,
        sortField: 'posts',
    },
];

type UsersTableProps = {
    data: UserRow[];
    isLoading?: boolean;
    emptyMessage?: string;
    sorting?: SortState | null;
    onSortChange?: (field: string) => void;
    pagination?: {
        page: number;
        pageSize: number;
        total: number;
        totalPages: number;
        onPageChange: (page: number) => void;
        onPageSizeChange?: (pageSize: number) => void;
    };
};

function UsersTable(props: Readonly<UsersTableProps>) {
    return (
        <Table<UserRow>
            headers={headers}
            data={props.data}
            rowKey={(row) => row.id}
            isLoading={props.isLoading}
            emptyMessage={props.emptyMessage}
            sorting={props.sorting}
            onSortChange={props.onSortChange}
            pagination={props.pagination}
        />
    );
}

function sortRows(data: UserRow[], sorting: SortState | null): UserRow[] {
    if (!sorting) {
        return data;
    }

    const sorted = [...data];
    sorted.sort((a, b) => {
        const left = a[sorting.field as keyof UserRow];
        const right = b[sorting.field as keyof UserRow];
        if (left === right) {
            return 0;
        }
        if (typeof left === 'number' && typeof right === 'number') {
            return sorting.direction === 'asc' ? left - right : right - left;
        }
        return sorting.direction === 'asc'
            ? String(left).localeCompare(String(right))
            : String(right).localeCompare(String(left));
    });
    return sorted;
}

const meta = {
    title: 'Components/Table',
    component: UsersTable,
    tags: ['autodocs'],
    parameters: {
        docs: {
            description: {
                component:
                    'Generic data table with loading/empty states, optional sorting controls, and optional pagination footer.',
            },
        },
    },
    argTypes: {
        data: {
            description: 'Rows rendered in the table body.',
            control: 'object',
            table: { type: { summary: 'UserRow[]' } },
        },
        isLoading: {
            description: 'When true, shows the loading indicator row.',
            control: 'boolean',
            table: { type: { summary: 'boolean' } },
        },
        emptyMessage: {
            description: 'Message shown when `data` is empty and `isLoading` is false.',
            control: 'text',
            table: { type: { summary: 'string' } },
        },
        sorting: {
            description: 'Current sort state object. Use `null` for no active sorting.',
            control: 'object',
            table: { type: { summary: "{ field: string; direction: 'asc' | 'desc' } | null" } },
        },
        onSortChange: {
            description: 'Callback fired when a sortable header is clicked.',
            action: 'sort changed',
            table: { type: { summary: '(field: string) => void' } },
        },
        pagination: {
            description: 'Pagination config object. When omitted, pagination footer is hidden.',
            control: 'object',
            table: {
                type: {
                    summary:
                        '{ page; pageSize; total; totalPages; onPageChange; onPageSizeChange? }',
                },
            },
        },
    },
    args: {
        data: rows,
    },
} satisfies Meta<typeof UsersTable>;

export default meta;
type Story = StoryObj<typeof meta>;

export const WithRows: Story = {};

export const Loading: Story = {
    args: {
        isLoading: true,
    },
};

export const Empty: Story = {
    args: {
        data: [],
        emptyMessage: 'No users found',
    },
};

export const InteractiveSortingAndPagination: Story = {
    render: () => {
        const [sorting, setSorting] = useState<SortState | null>({
            field: 'name',
            direction: 'asc',
        });
        const [page, setPage] = useState(1);
        const [pageSize, setPageSize] = useState(5);

        const sorted = useMemo(() => sortRows(rows, sorting), [sorting]);
        const totalPages = Math.max(1, Math.ceil(sorted.length / pageSize));
        const safePage = Math.min(page, totalPages);
        const start = (safePage - 1) * pageSize;
        const pagedRows = sorted.slice(start, start + pageSize);

        return (
            <UsersTable
                data={pagedRows}
                sorting={sorting}
                onSortChange={(field) => {
                    setPage(1);
                    setSorting((prev) => {
                        if (!prev || prev.field !== field) {
                            return { field, direction: 'asc' };
                        }
                        if (prev.direction === 'asc') {
                            return { field, direction: 'desc' };
                        }
                        return null;
                    });
                }}
                pagination={{
                    page: safePage,
                    pageSize,
                    total: sorted.length,
                    totalPages,
                    onPageChange: setPage,
                    onPageSizeChange: (next) => {
                        setPage(1);
                        setPageSize(next);
                    },
                }}
            />
        );
    },
};
