import {
    useCallback,
    useMemo,
} from 'react';

import _ from 'lodash';
import {
    ArrowDownIcon,
    ArrowUpDownIcon,
    ArrowUpIcon,
    GripHorizontal,
} from 'lucide-react';

import {
    CollectionRelationType,
    DatumIMType,
    SortDFInput,
    StructureType,
} from '@/api/types';
import { MenuData } from '@/components/AnyDropdownMenu';
import { Checkbox } from '@/components/ui/checkbox';
import { Skeleton } from '@/components/ui/skeleton';
import {
    Table,
    TableBody,
    TableCell,
    TableHead,
    TableHeader,
    TableRow,
} from '@/components/ui/table';
import { useAppConfig } from '@/contexts/AppConfigContext';
import type { DragEndEvent } from '@dnd-kit/core';
import { DndContext } from '@dnd-kit/core';
import { restrictToVerticalAxis } from '@dnd-kit/modifiers';
import {
    arrayMove,
    SortableContext,
    useSortable,
    verticalListSortingStrategy,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

import {
    ColumnsType,
    getColumnsInternal,
} from '../utils';
import EmptyTable from './EmptyTable';
import { getFastMenu } from './SelectedRowButton';

type TableViewProps = {
    sortable: boolean;
    loading: boolean;
    onDoAction: (item: StructureType, row_id?: string) => void;
    data: DatumIMType[];
    selectedRows: string[];
    onSelectAll: () => void;
    sort: SortDFInput | null;
    onSelectRow: (id: string | undefined) => void;
    onEditFields: (item: StructureType, row_id?: string) => void;
    onClickSort: (column: any) => void;
    onCreate: () => void;
    structure: StructureType | null;
    onOpenRelationTable: (item: CollectionRelationType, row_id: string) => void;
    onReorder?: (activeIndex: number, overIndex: number, newData: DatumIMType[]) => void;
    onDeleteSelected: (row_id?: string) => void;
    relations: CollectionRelationType[];
}




const TableSkeletonRow = ({ count }: { count: number }) => {
    return <TableRow>
        {[...Array(count)].map((index) => (
            <TableCell key={index}>
                <Skeleton className="w-full h-6" />
            </TableCell>
        ))}
    </TableRow>
}


const TableSkeleton = () => {
    return <Table style={{ width: '100%' }}>



        <TableHeader>
            <TableRow header>

                {[1, 2, 3, 4, 5]?.map((index) => (
                    <TableHead key={index} >
                        <Skeleton
                            className="w-full h-6"
                        />
                    </TableHead>
                ))}
            </TableRow>
        </TableHeader>
        <TableBody>
            {[1, 2, 3]?.map((index) => (
                <TableSkeletonRow key={index} count={5} />
            ))}



        </TableBody>


    </Table>
}



const TableView = ({ loading, sortable, data, relations, onOpenRelationTable, onDoAction, selectedRows, onSelectAll, onDeleteSelected, onEditFields, sort, onSelectRow, onClickSort, onCreate, structure, onReorder }: TableViewProps) => {
    const { openDialog } = useAppConfig();


    const columns = useMemo(() => {

        if (!structure) return () => [] as ColumnsType[];

        return () => getColumnsInternal(false, structure ?? {});
    }, [structure?.items]);


    const contextMenuItems = useCallback((row_id: string): MenuData[] => {

        if (sortable) return [];

        if (!structure) return [];


        return getFastMenu({
            onOpenRelationTable: (item: CollectionRelationType) => {
                onOpenRelationTable(item, row_id);
            },
            relations,
            structure,
            onEditFields: (item: StructureType) => {

                onEditFields?.(item, row_id);

            },
            onDoAction: (item: StructureType) => {

                onDoAction?.(item, row_id);

            }, onDeleteSelected: () => {

                onDeleteSelected?.(row_id);

            }, onExportSelected: () => { }, forOneRow: true
        });

    }, [structure, sortable, relations]);

    const onDragEnd = ({ active, over }: DragEndEvent) => {
        if (!over || active.id === over.id || !onReorder) {
            return;
        }

        const activeIndex = data.findIndex((record) => record._id === active.id);
        const overIndex = data.findIndex((record) => record._id === over.id);

        if (activeIndex === -1 || overIndex === -1) {
            return;
        }

        const newData = arrayMove(data, activeIndex, overIndex);
        onReorder(activeIndex, overIndex, newData);
    };


    const SortableWrapper = ({ children }: { children: React.ReactNode }) => {

        if (!sortable) return children;

        return <DndContext modifiers={[restrictToVerticalAxis]} onDragEnd={onDragEnd}>
            <SortableContext items={(data ?? []).map((i) => i._id!)} strategy={verticalListSortingStrategy}>
                {children}
            </SortableContext>
        </DndContext>

    }


    const TableRowRender = ({ item }: { item: DatumIMType }) => {
        let style: React.CSSProperties = {};
        let setNodeRef: ((node: HTMLElement | null) => void) | undefined;
        let setActivatorNodeRef: ((node: HTMLElement | null) => void) | undefined;
        let attributes: any;
        let listeners: any;

        if (sortable) {
            const sortableProps = useSortable({ id: item._id! });
            setNodeRef = sortableProps.setNodeRef;
            setActivatorNodeRef = sortableProps.setActivatorNodeRef;
            attributes = sortableProps.attributes;
            listeners = sortableProps.listeners;

            style = {
                transform: CSS.Translate.toString(sortableProps.transform),
                transition: sortableProps.transition,
                ...(sortableProps.isDragging ? { position: 'relative', zIndex: 9999 } : {}),
            };
        }





        return <TableRow

            contextMenuItems={contextMenuItems(item._id!)}
            ref={sortable ? setNodeRef : undefined}
            style={sortable ? style : undefined}
            onClick={(e) => {
                if (sortable) return;

                if (selectedRows.length > 0) {
                    onSelectRow(item._id);
                } else {
                    openDialog({
                        modalKey: `collection_view_${structure?.collection}_${item._id}`,
                        collection: structure?.collection ?? "",
                        _id: item._id,
                    });
                }

            }}
            key={item._id}>



            <TableCell
                onClick={(e) => {
                    e.stopPropagation();
                    e.preventDefault();
                    if (!sortable) {
                        onSelectRow(item._id);
                    }
                }}
                className="cursor-pointer"
            >
                {loading ? <Skeleton className="w-full h-6" /> : sortable ? (
                    <div
                        ref={setActivatorNodeRef}
                        {...attributes}
                        {...listeners}
                        className="cursor-grab active:cursor-grabbing"
                    >
                        <GripHorizontal className='size-4' />
                    </div>
                ) : (
                    <Checkbox checked={item._id ? selectedRows.includes(item._id) : false} onCheckedChange={(checked) => {
                        onSelectRow(item._id);
                    }} />
                )}
            </TableCell>

            {columns()?.map((column) => {

                let value = _.get(item, column.dataIndex);

                return <TableCell
                    style={{
                        opacity: loading ? 0.3 : 1,
                        transition: 'opacity 0.2s ease-in-out',
                    }}
                    key={column.key}>

                    {column.render(value, item)}
                </TableCell>
            })}


        </TableRow>
    }


    return <div
        className="rounded-md  overflow-auto relative"
        style={{
            //    height: window.innerHeight - headerHeight - 100,

        }}
    >






        {!structure && <TableSkeleton />}


        {structure && <SortableWrapper>
            <Table style={{ width: '100%' }}>



                <TableHeader>
                    <TableRow header>
                        <TableHead

                            onClick={(e) => {



                                if (sortable) return;


                                if (data?.length == 0) return;



                                onSelectAll();

                                e.stopPropagation();
                                e.preventDefault();
                            }}
                            className="sticky top-0 bg-background z-10 shadow-sm">
                            {sortable ? <GripHorizontal className='size-4' /> : <Checkbox
                                style={{

                                    pointerEvents: 'none',
                                }}
                                disabled={data?.length == 0}
                                checked={selectedRows.length > 0 && selectedRows.length == data?.length}

                            //onCheckedChange={onSelectAll}
                            />}
                        </TableHead>
                        {columns()?.map((column) => (
                            <TableHead key={column.key} className="sticky top-0 bg-background z-10 shadow-sm">
                                <div
                                    onClick={() => {
                                        onClickSort(column);
                                    }}
                                    className="flex items-center gap-2 cursor-pointer">
                                    {column.sorter ?

                                        sort?.field == column.dataIndex ? sort?.direction == "ASC" ? <ArrowUpIcon className='opacity-50' size={13} /> : <ArrowDownIcon className='opacity-50' size={13} /> :
                                            <ArrowUpDownIcon className='opacity-50' size={13} /> : null}  {column.title()}
                                </div>
                            </TableHead>
                        ))}
                    </TableRow>
                </TableHeader>


                <TableBody>

                    {!loading && data?.length == 0 && <TableRow>
                        <TableCell colSpan={(columns()?.length ?? 0) + 1}>
                            <EmptyTable title={structure?.title} onCreate={onCreate} />
                        </TableCell>
                    </TableRow>
                    }



                    {loading && data.length == 0 &&
                        [1, 2, 3]?.map((index) => (
                            <TableSkeletonRow key={index} count={(columns()?.length ?? 0) + 1} />
                        ))}




                    {data?.length > 0 && data?.map((item, index) => (
                        <TableRowRender key={item._id} item={item} />
                    ))}



                </TableBody>


            </Table>
        </SortableWrapper>
        }


    </div>
}

export default TableView;