import { useMemo, cloneElement, Fragment, FC, ReactElement } from 'react';

import { provide, useDependencies } from '@servicetitan/react-ioc';

import { observer } from 'mobx-react';

import { Stack, ButtonGroup, Button, Tag, DatePicker } from '@servicetitan/design-system';

import {
    Table,
    TableColumn,
    TableCell,
    TableCellProps,
    TextEditableCell,
    BooleanEditableCell,
    getSelectEditableCell,
    DateRangeColumnMenuFilter,
    StandardColumnMenuFilter,
    standardFilterWithMultiselect,
    multiSelectColumnMenuFilter,
    CurrencyRangeColumnMenuFilter,
    getEditableCell,
    EditorProps,
} from '../..';
import { Export } from '../../export';

import { TableStore } from './table.store';

import { ActionsCell } from './actions-cell';

import { NumberInput, enumToOptions, getEnumKeys } from '@servicetitan/form';
import { Product, UserRole, Supplier } from './product';

const UserRoleColumnMenuFilter = multiSelectColumnMenuFilter(getEnumKeys(UserRole), userRole => (
    <Tag compact color={UserRole[userRole] === UserRole.Owner ? 'success' : 'default'}>
        {userRole}
    </Tag>
));

const AvailableForEditableCell = getSelectEditableCell({
    options: enumToOptions(UserRole),
    viewer: ({ dataItem, field, tdProps }) => {
        const value = dataItem[field!];

        return <td {...tdProps}>{value && UserRole[value]}</td>;
    },
});

const SupplierCell: FC<TableCellProps> = props => {
    const { field, dataItem, rowType, tdProps } = props;

    if (rowType !== 'data') {
        return <TableCell {...props} />;
    }

    return <td {...tdProps}>{Supplier[dataItem[field!]]}</td>;
};

// Implementation of a date editable cell utilizing getEditableCell
const DateEditor = observer<FC<EditorProps<Date | string | undefined>>>(
    ({ fieldState: { value, onChange, hasError }, className, tdProps }) => {
        return (
            <td className={className} {...tdProps}>
                <DatePicker value={value} onChange={onChange} error={hasError} />
            </td>
        );
    }
);
export const DateEditableCell = getEditableCell({
    editor: DateEditor,
});

// Implementation of a numeric editable cell utilizing getEditableCell
const NumberCellEditor: FC<EditorProps<number>> = observer(
    ({ fieldState: { value, hasError, onChange }, tdProps }) => (
        <td {...tdProps}>
            <NumberInput
                onChange={onChange}
                type="number"
                error={hasError}
                value={value}
                emptyValue={0}
                min={0}
                max={1000}
                useEmptyThousandsSeparator
                fluid
                decimalPlaces={2}
                useKeyboardNavigation
            />
        </td>
    )
);
const NumericEditableCell = getEditableCell({
    editor: getEditableCell({ editor: NumberCellEditor }),
});

export const TableExample: FC = provide({
    singletons: [TableStore],
})(
    observer(() => {
        const [{ tableState, inEdit, editAll, cancelAll, saveAll }] = useDependencies(TableStore);

        const madeInColumnMenu = useMemo(
            () => standardFilterWithMultiselect({ tableState }),
            [tableState]
        );

        const cellRender = (td: ReactElement | null, { dataItem, field }: TableCellProps) => {
            if (!td) {
                return null;
            }

            return cloneElement(td, {
                onClick: () => {
                    tableState.edit(dataItem, field as keyof Product);
                },
            });
        };

        return (
            <Fragment>
                <Stack justifyContent="space-between" alignContent="center" className="m-b-2">
                    <Export
                        totalCount={tableState.totalCount}
                        exportPdf={tableState.exportPdf}
                        exportExcel={tableState.exportExcel}
                    />
                    {inEdit ? (
                        <ButtonGroup>
                            <Button small onClick={cancelAll} className="m-r-2">
                                Cancel All
                            </Button>

                            <Button small primary onClick={saveAll}>
                                Save All
                            </Button>
                        </ButtonGroup>
                    ) : (
                        <Button small primary onClick={editAll}>
                            Edit All
                        </Button>
                    )}
                </Stack>

                <Table
                    tableState={tableState}
                    striped={false}
                    selectable
                    groupable
                    sortable
                    exportable
                    exportFileName="Table.Export.Test...File.Name.01.01.2020..~!@#$%^(*_+';"
                    cellRender={cellRender}
                    navigatable
                >
                    <TableColumn field="ProductID" title="ID" editable={false} width="100px" />

                    <TableColumn
                        field="ProductName"
                        title="Product Name"
                        cell={TextEditableCell}
                        columnMenu={StandardColumnMenuFilter}
                        width="240px"
                    />

                    <TableColumn
                        field="Supplier"
                        title="Supplier"
                        cell={SupplierCell}
                        columnMenu={StandardColumnMenuFilter}
                        width="150px"
                    />

                    <TableColumn
                        field="MadeIn"
                        title="Made In"
                        cell={TextEditableCell}
                        columnMenu={madeInColumnMenu}
                        width="175px"
                    />

                    <TableColumn
                        field="UnitsOnOrder"
                        title="First Ordered On"
                        cell={DateEditableCell}
                        columnMenu={DateRangeColumnMenuFilter}
                        format="{0:MM/dd/yyyy}"
                        width="240px"
                    />

                    <TableColumn
                        field="UnitPrice"
                        title="Unit Price"
                        cell={NumericEditableCell}
                        columnMenu={CurrencyRangeColumnMenuFilter}
                        format="{0:c}"
                        width="125px"
                    />

                    <TableColumn
                        field="Discontinued"
                        title="Discontinued"
                        cell={BooleanEditableCell}
                        sortable={false}
                        width="125px"
                    />

                    <TableColumn
                        field="AvailableFor"
                        title="Available For"
                        cell={AvailableForEditableCell}
                        columnMenu={UserRoleColumnMenuFilter}
                        width="240px"
                    />

                    <TableColumn cell={ActionsCell} sortable={false} width="125px" />
                </Table>
            </Fragment>
        );
    })
);
