import { FC } from "react";
import styles from "./DealsDndColumn.module.css";
import { Draggable, Droppable } from "@hello-pangea/dnd";
import CreateCardButton from "../CreateCardButton/CreateCardButton.tsx";
import { CardGroupSchema, CardSummary, StatusSchema } from "../../../../client";
import CardSummaryItem from "../CardSummaryItem/CardSummaryItem.tsx";
import classNames from "classnames";
import { groupBy, has, uniq } from "lodash";
import { CardGroupView } from "../CardGroupView/CardGroupView.tsx";
import CreateDealsFromFileButton from "../CreateCardsFromFileButton/CreateDealsFromFileButton.tsx";
import DragState from "../../../../pages/CardsPage/enums/DragState.ts";
import isModuleInProject, { Modules } from "../../../../modules/utils/isModuleInProject.ts";
import { useProjectsContext } from "../../../../contexts/ProjectsContext.tsx";

type Props = {
    status: StatusSchema;
    withCreateButton?: boolean;
    summaries: CardSummary[];
    dragState: DragState;
};

type GroupWithCards = { group: CardGroupSchema, cards: CardSummary[] }

export const CardsDndColumn: FC<Props> = ({
                                              status,
                                              summaries,
                                              dragState,
                                              withCreateButton = false,
                                          }) => {
    const { selectedProject } = useProjectsContext();
    const isCreatingDealFromFileEnabled = isModuleInProject(Modules.SERVICES_AND_PRODUCTS, selectedProject);
    const isDropDisabled = dragState === DragState.DRAG_STATUS;
    const droppableId = status.id.toString();

    const isGroup = (obj: GroupWithCards | CardSummary): obj is GroupWithCards => {
        return has(obj, "cards");
    };

    const getCardGroups = (): GroupWithCards[] => {
        const groups = uniq<CardGroupSchema>(summaries.filter(s => s.group).map(summary => summary.group) as CardGroupSchema[]);
        if (groups.length === 0) return [];
        const groupedSummaries = groupBy(summaries, "group.id");
        const groupDict = groups.reduce((acc, group) => {
            acc[group.id] = group;
            return acc;
        }, {} as { [key: number]: CardGroupSchema });
        return Object.entries(groupedSummaries).reduce((acc, [groupId, cards]) => {
            if (!groupId) return acc;
            const group = groupDict[parseInt(groupId)];
            if (!group) return acc;
            acc.push({
                group,
                cards,
            });
            return acc;
        }, [] as { group: CardGroupSchema; cards: CardSummary[] }[]);
    };

    const getCardsAndGroups = (): (GroupWithCards | CardSummary)[] => {
        const groups = getCardGroups();
        const cards = summaries.filter(s => !s.group).sort((a, b) => {
            return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
        });
        return [...cards, ...groups].map((obj, index) => {
            if (isGroup(obj)) {
                obj.cards[0].rank = index;
                return obj;
            }
            obj.rank = index;
            return obj;
        }) as (GroupWithCards | CardSummary)[];
    };

    const renderCard = (card: CardSummary) => {
        return (
            <Draggable
                draggableId={card.id.toString()}
                index={card.rank}
                key={card.id}>
                {(provided, snapshot) => (
                    <div
                        {...provided.draggableProps}
                        {...provided.dragHandleProps}
                        ref={provided.innerRef}>
                        <div
                            style={{
                                transition: "transform 0.1s ease-in-out",
                                transform: snapshot.combineWith ? "scale(0.85)" : "none",
                                color: snapshot.combineWith ? "red" : "black",
                            }}
                        >
                            <CardSummaryItem cardSummary={card} />
                        </div>
                    </div>
                )}
            </Draggable>
        );
    };
    const renderGroup = (obj: GroupWithCards) => {
        const { cards, group } = obj;
        return (
            <Draggable
                draggableId={"group-" + group.id}
                index={cards[0].rank}
                key={"group-" + group.id}
            >
                {(provided) => (
                    <div
                        {...provided.draggableProps}
                        {...provided.dragHandleProps}
                        ref={provided.innerRef}
                    >
                        <CardGroupView
                            cards={cards}
                            group={group}
                        />
                    </div>
                )}
            </Draggable>
        );
    };
    return (
        <Droppable
            isDropDisabled={isDropDisabled}
            isCombineEnabled
            droppableId={droppableId}>
            {(provided, snapshot) => (
                <div
                    ref={provided.innerRef}
                    className={classNames(
                        styles["items-list"],
                        snapshot.isDraggingOver &&
                        !snapshot.draggingFromThisWith &&
                        styles["items-list-drag-over"],
                    )}
                    {...provided.droppableProps}>
                    {withCreateButton && (
                        <>
                            <CreateCardButton status={status} />
                            {
                                isCreatingDealFromFileEnabled &&
                                (<CreateDealsFromFileButton />)
                            }
                        </>
                    )}
                    {getCardsAndGroups().map(obj => {
                        if (isGroup(obj)) {
                            return renderGroup(obj);
                        }
                        return renderCard(obj);
                    })}
                    {provided.placeholder}
                </div>
            )}
        </Droppable>
    );
};

export default CardsDndColumn;

