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

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

import { rpc } from '@/api/request';
import {
    AdminActionMenuItemType,
    CollectionAccessType,
    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 { LL } from '@/lang/LL';
import { useAppConfig } from '@/stores/appConfig';
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 = {
    collectionAccess: CollectionAccessType | null;
    sortable: boolean;
    loading: boolean;
    onDoAction: (item: AdminActionMenuItemType, row_id?: string) => void;
    data: DatumIMType[];
    selectedRows: string[];
    onClearSelected: () => void;
    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, onClearSelected, onOpenRelationTable, onDoAction, selectedRows, onSelectAll, onDeleteSelected, onEditFields, sort, onSelectRow, onClickSort, onCreate, structure, onReorder, collectionAccess }: TableViewProps) => {
    const { openDialog } = useAppConfig();


    const columns = useMemo(() => {

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

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



    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 }) => {
        const [rowAccess, setRowAccess] = useState<CollectionAccessType | null>(null);
        const [rowActions, setRowActions] = useState<AdminActionMenuItemType[]>([]);
        const [rowAccessLoading, setRowAccessLoading] = useState(false);

        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 } : {}),
            };
        }

        const onContextMenuOpen = () => {
            if (!structure?.collection || !item._id) return;
            setRowAccess(null);
            setRowActions([]);
            setRowAccessLoading(true);

            const collection = structure.collection;
            const ids = [item._id];

            Promise.all([
                rpc.collectionAccess({ collection, ids }),
                rpc.allActions({ collection, _ids: ids }),
            ]).then(([accessData, actionsData]) => {
                setRowAccess(accessData?.result ?? null);
                setRowActions(actionsData?.result ?? []);
            }).catch(() => {
                setRowAccess(null);
                setRowActions([]);
            }).finally(() => {
                setRowAccessLoading(false);
            });
        };

        const rowMenuItems: MenuData[] = sortable ? [] : getFastMenu({
            collectionAccess: rowAccess,
            onOpenRelationTable: (rel: CollectionRelationType) => { onOpenRelationTable(rel, item._id!); },
            onClearSelected: () => { onClearSelected(); },
            relations,
            structure,
            onEditFields: (field: StructureType) => { onEditFields?.(field, item._id!); },
            onDoAction: (action: AdminActionMenuItemType) => { onDoAction?.(action, item._id!); },
            onDeleteSelected: () => { onDeleteSelected?.(item._id!); },
            onExportSelected: () => { },
            forOneRow: true,
            actions: rowActions,
        });





        return <TableRow
            contextMenuItems={rowMenuItems}
            onContextMenuOpen={sortable ? undefined : onContextMenuOpen}
            contextMenuLoading={rowAccessLoading}
            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"
            >
                {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={<LL value={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;