"use client";

import React, { ReactNode } from "react";
import {
    closestCorners,
    DndContext,
    DragEndEvent,
    DragOverEvent,
    DragStartEvent,
} from "@dnd-kit/core";
import {
    horizontalListSortingStrategy,
    SortableContext,
} from "@dnd-kit/sortable";
import { Group, ScrollArea } from "@mantine/core";
import useDndSensors from "@/app/deals/hooks/useSensors";
import SortableItem from "@/components/dnd/SortableItem";
import { BaseDraggable } from "@/components/dnd/types/types";
import FunnelColumn from "./FunnelColumn";
import FunnelOverlay from "./FunnelOverlay";

type Props<TContainer, TItem> = {
    containers: TContainer[];
    items: TItem[];
    onDragStart: (event: DragStartEvent) => void;
    onDragOver: (event: DragOverEvent) => void;
    onDragEnd: (event: DragEndEvent) => void;
    renderContainer: (container: TContainer, children: ReactNode) => ReactNode;
    renderContainerOverlay: (
        container: TContainer,
        children: ReactNode
    ) => ReactNode;
    renderItem: (item: TItem) => ReactNode;
    renderItemOverlay: (item: TItem) => ReactNode;
    getContainerId: (container: TContainer) => string;
    getItemsByContainer: (container: TContainer, items: TItem[]) => TItem[];
    activeContainer: TContainer | null;
    activeItem: TItem | null;
};

const FunnelDnd = <
    TContainer extends BaseDraggable,
    TItem extends BaseDraggable,
>({
    containers,
    items,
    onDragStart,
    onDragOver,
    onDragEnd,
    renderContainer,
    renderContainerOverlay,
    renderItem,
    renderItemOverlay,
    getContainerId,
    getItemsByContainer,
    activeContainer,
    activeItem,
}: Props<TContainer, TItem>) => {
    const sensors = useDndSensors();

    return (
        <ScrollArea
            offsetScrollbars="x"
            scrollbarSize="0.5rem">
            <DndContext
                sensors={sensors}
                collisionDetection={closestCorners}
                onDragStart={onDragStart}
                onDragOver={onDragOver}
                onDragEnd={onDragEnd}>
                <SortableContext
                    items={containers.map(getContainerId)}
                    strategy={horizontalListSortingStrategy}>
                    <Group
                        gap="xs"
                        wrap="nowrap"
                        align="start">
                        {containers.map(container => {
                            const containerItems = getItemsByContainer(
                                container,
                                items
                            );
                            const containerId = getContainerId(container);
                            return (
                                <SortableItem
                                    key={containerId}
                                    id={containerId}>
                                    {renderContainer(
                                        container,
                                        <FunnelColumn
                                            id={containerId}
                                            items={containerItems}
                                            renderItem={renderItem}
                                        />
                                    )}
                                </SortableItem>
                            );
                        })}
                        <FunnelOverlay
                            activeContainer={activeContainer}
                            activeItem={activeItem}
                            renderContainer={container => {
                                const containerItems = getItemsByContainer(
                                    container,
                                    items
                                );
                                const containerId = getContainerId(container);
                                return renderContainerOverlay(
                                    container,
                                    <FunnelColumn
                                        id={containerId}
                                        items={containerItems}
                                        renderItem={renderItem}
                                    />
                                );
                            }}
                            renderItem={renderItemOverlay}
                        />
                    </Group>
                </SortableContext>
            </DndContext>
        </ScrollArea>
    );
};

export default FunnelDnd;
