import { useState } from 'react';
import { IconPlus } from '@tabler/icons-react';
import { CreateField } from '../interfaces/create';
import { AxiosResponse } from 'axios';
import FormFields from './FormFields';
import { Badge, Button, createTableColumn, DataGrid, DataGridBody, DataGridCell, DataGridHeader, DataGridHeaderCell, DataGridRow, Dialog, DialogSurface, DialogTitle, DialogTrigger, Input, Select, Spinner, TableCellLayout, TableColumnDefinition } from '@fluentui/react-components';
import { IColumn } from '../interfaces/DataGrid/columns';

type CustomTableProps<T> = {
    data: (T & { id: number })[];
    columns: IColumn[];
    createFields?: CreateField[];
    submitHandler?: (data: T) => Promise<AxiosResponse>
    onEditCell?: (rowId: number, columnId: string, value: any) => any
    searchable?: boolean
    isLoading?: boolean
}

const CustomTable = <T extends object>({
    data: initialData,
    columns,
    createFields,
    submitHandler,
    searchable = false,
    isLoading = false
}: CustomTableProps<T>) => {
    const [data, setData] = useState<(T & { id: number })[]>(initialData);
    const [searchText, setSearchText] = useState('');

    const [editingCell, setEditingCell] = useState<{
        rowId: number | null
        columnId: string | null
    }>({ rowId: null, columnId: null })

    const handleEditCell = (rowId: number, columnId: string, value: any) => {
        setData((prev) =>
            prev.map((row) =>
                row.id === rowId ? { ...row, [columnId]: value } : row
            )
        )
    }

    const columnDefinitions: TableColumnDefinition<any>[] = columns.filter(column => column.hidden !== true).map(column => (
        createTableColumn<any>({
            columnId: column.name,
            renderHeaderCell: () => column.header,
            renderCell: (item) => {
                const isEditing = editingCell.rowId === item.id && editingCell.columnId === column.name;

                switch (column.type) {
                    case 'number':
                        return (
                            <TableCellLayout
                                truncate
                                onDoubleClick={() =>
                                    setEditingCell({ rowId: item.id, columnId: column.name })
                                }
                            >
                                {isEditing ? (
                                    <Input
                                        value={item[column.name]}
                                        onChange={(_, d) => handleEditCell?.(item.id, column.name, d.value)}
                                        onBlur={() => setEditingCell({ rowId: null, columnId: null })}
                                        autoFocus
                                    />
                                ) : (
                                    item[column.name]
                                )}
                            </TableCellLayout>
                        )
                    case 'string':
                        return (
                            <TableCellLayout
                                truncate
                                onDoubleClick={() =>
                                    setEditingCell({ rowId: item.id, columnId: column.name })
                                }
                            >
                                {isEditing ? (
                                    <Input
                                        value={item[column.name]}
                                        onChange={(_, d) => handleEditCell?.(item.id, column.name, d.value)}
                                        onBlur={() => setEditingCell({ rowId: null, columnId: null })}
                                        autoFocus
                                    />
                                ) : (
                                    item[column.name]
                                )}
                            </TableCellLayout>
                        )
                    case 'boolean':
                        return (
                            <TableCellLayout onDoubleClick={() =>
                                setEditingCell({ rowId: item.id, columnId: column.name })
                            }>
                                {isEditing ? (
                                    <Select
                                        value={item[column.name]}
                                        onChange={(_, d) => handleEditCell?.(item.id, column.name, d.value)}
                                        onBlur={() => setEditingCell({ rowId: null, columnId: null })}>
                                        <option value='true'>Активен</option>
                                        <option value='false'>Неактивен</option>
                                    </Select>
                                ) : (
                                    <Badge color={JSON.parse(item[column.name]) === true ? 'success' : 'danger'}>
                                        {JSON.parse(item[column.name]) === true ? 'Активен' : 'Неактивен'}
                                    </Badge>
                                )}
                            </TableCellLayout>
                        )
                    case 'dictionary':
                        return (
                            <TableCellLayout
                                onDoubleClick={() =>
                                    setEditingCell({ rowId: item.id, columnId: column.name })
                                }
                            >
                                {isEditing ? (
                                    <Input
                                        value={item[column.name]}
                                        onChange={(_, d) => handleEditCell?.(item.id, column.name, d.value)}
                                        onBlur={() => setEditingCell({ rowId: null, columnId: null })}
                                        autoFocus
                                    />
                                ) : (
                                    item[column.name]
                                )}
                            </TableCellLayout>
                        )
                }
            },
        })
    ))

    return (
        <div style={{
            display: 'flex',
            flexDirection: 'column',
            gap: '1rem'
        }}>
            <div style={{
                display: 'flex',
                gap: '1rem'
            }}>
                {searchable &&
                    <Input
                        placeholder="Поиск"
                        value={searchText}
                        onChange={(e) => setSearchText(e.target.value)}
                    />}

                {createFields && submitHandler &&
                    <Dialog>
                        <DialogTrigger>
                            <Button
                                appearance='primary'
                                icon={<IconPlus />}
                                style={{ flexShrink: 0 }}
                            >
                                Добавить
                            </Button>
                        </DialogTrigger>

                        <DialogSurface>
                            <DialogTitle>Добавление объекта</DialogTitle>
                            <FormFields
                                fields={createFields}
                                submitHandler={submitHandler}
                            />
                        </DialogSurface>
                    </Dialog>
                }
            </div>

            {isLoading ?
                <Spinner />
                :
                <DataGrid
                    items={data}
                    columns={columnDefinitions}
                    resizableColumns
                    sortable
                    getRowId={(item) => item.name}
                    focusMode="cell"
                >
                    <DataGridHeader>
                        <DataGridRow>
                            {({ renderHeaderCell }) => (
                                <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>
                            )}
                        </DataGridRow>
                    </DataGridHeader>
                    <DataGridBody<CustomTableProps<T>>>
                        {({ item, rowId }) => (
                            <DataGridRow key={rowId}>
                                {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
                            </DataGridRow>
                        )}
                    </DataGridBody>
                </DataGrid>
            }
        </div>
    );
};

export default CustomTable;
