"use client";

import React, { ReactNode, RefObject, useMemo } from "react";
import {
    DndContext,
    DragEndEvent,
    DragOverEvent,
    DragStartEvent,
} from "@dnd-kit/core";
import {
    horizontalListSortingStrategy,
    SortableContext,
} from "@dnd-kit/sortable";
import { FreeMode, Pagination, Scrollbar } from "swiper/modules";
import { Swiper, SwiperRef, SwiperSlide } from "swiper/react";
import { Box } from "@mantine/core";
import CreateStatusButton from "@/app/deals/components/shared/CreateStatusButton/CreateStatusButton";
import useDndSensors from "@/app/deals/hooks/useSensors";
import FunnelColumn from "@/components/dnd/FunnelDnd/FunnelColumn";
import FunnelOverlay from "@/components/dnd/FunnelDnd/FunnelOverlay";
import { BaseDraggable } from "@/components/dnd/types/types";
import useIsMobile from "@/hooks/utils/useIsMobile";
import SortableItem from "../SortableItem";
import classes from "./FunnelDnd.module.css";

type Props<TContainer, TItem> = {
    containers: TContainer[];
    items: TItem[];
    onDragStart: (event: DragStartEvent) => void;
    onDragOver: (event: DragOverEvent) => void;
    onDragEnd: (event: DragEndEvent) => void;
    swiperRef: RefObject<SwiperRef | null>;
    renderContainer: (
        container: TContainer,
        children: ReactNode,
        renderDraggable: () => ReactNode,
        index: number
    ) => ReactNode;
    renderContainerHeader: (container: TContainer) => 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;
    isCreatingContainerEnabled?: boolean;
    disabledColumns?: boolean;
};

const FunnelDnd = <
    TContainer extends BaseDraggable,
    TItem extends BaseDraggable,
>({
    containers,
    items,
    onDragStart,
    onDragOver,
    onDragEnd,
    swiperRef,
    renderContainer,
    renderContainerHeader,
    renderContainerOverlay,
    renderItem,
    renderItemOverlay,
    getContainerId,
    getItemsByContainer,
    activeContainer,
    activeItem,
    isCreatingContainerEnabled = true,
    disabledColumns = false,
}: Props<TContainer, TItem>) => {
    const sensors = useDndSensors();
    const isMobile = useIsMobile();
    const frequency = useMemo(() => (isMobile ? 1 : undefined), [isMobile]);

    const renderContainers = () =>
        containers.map((container, index) => {
            const containerItems = getItemsByContainer(container, items);
            const containerId = getContainerId(container);
            return (
                <SwiperSlide
                    style={{ width: 250 }}
                    key={containerId}>
                    <SortableItem
                        key={containerId}
                        id={containerId}
                        disabled={disabledColumns}
                        renderItem={renderDraggable =>
                            renderContainer(
                                container,
                                <FunnelColumn
                                    id={containerId}
                                    items={containerItems}
                                    renderItem={renderItem}
                                />,
                                renderDraggable!,
                                index
                            )
                        }
                        renderDraggable={() => renderContainerHeader(container)}
                    />
                </SwiperSlide>
            );
        });

    const renderBody = () => {
        if (isMobile) {
            return (
                <Box>
                    <Swiper
                        ref={swiperRef}
                        onTouchStart={swiper => {
                            swiper.allowTouchMove = !activeItem;
                        }}
                        onTouchMove={swiper => {
                            swiper.allowTouchMove = !activeItem;
                        }}
                        className={classes["swiper-container"]}
                        spaceBetween={15}
                        style={{ paddingInline: "10vw" }}
                        modules={[Pagination]}
                        freeMode={{ enabled: false }}
                        pagination={{ enabled: true, clickable: true }}>
                        {renderContainers()}
                        {isCreatingContainerEnabled && (
                            <SwiperSlide style={{ width: 250 }}>
                                <CreateStatusButton />
                            </SwiperSlide>
                        )}
                    </Swiper>
                </Box>
            );
        }
        return (
            <Swiper
                ref={swiperRef}
                className={classes["swiper-container"]}
                modules={[Scrollbar, FreeMode]}
                spaceBetween={15}
                slidesPerView={"auto"}
                scrollbar={{ hide: false }}
                freeMode={{ enabled: true }}
                touchStartPreventDefault={false}
                grabCursor>
                {renderContainers()}
                {isCreatingContainerEnabled && (
                    <SwiperSlide style={{ width: 50 }}>
                        <CreateStatusButton />
                    </SwiperSlide>
                )}
            </Swiper>
        );
    };

    return (
        <DndContext
            sensors={sensors}
            measuring={{
                droppable: {
                    frequency,
                },
            }}
            onDragStart={onDragStart}
            onDragOver={onDragOver}
            onDragEnd={onDragEnd}>
            <SortableContext
                items={containers.map(getContainerId)}
                strategy={horizontalListSortingStrategy}>
                {renderBody()}
                <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}
                />
            </SortableContext>
        </DndContext>
    );
};

export default FunnelDnd;
