import { KanbanDragAndDropContext } from './KanbanDragAndDropContext';
import { KanbanDraggableCardItem } from './KanbanDraggableCardItem';
import { KanbanDragOverlay } from './KanbanDragOverlay';
import { action, makeObservable, observable } from 'mobx';
import { v4 as uuid } from 'uuid';
export class KanbanDragAndDropState {
    constructor(params) {
        this.activeId = null;
        this.status = 'start';
        this._moveId = '';
        this.setActiveId = (id) => {
            this.activeId = id;
        };
        this.handleDragStart = (event) => {
            this._moveId = uuid();
            this.status = 'start';
            this.activeId = event.active.id.toString();
            const keyedItem = this._findItemById(this.activeId);
            const stageId = this._findStageByItemId(this.activeId);
            if (!keyedItem || !stageId) {
                return;
            }
            this.kanbanState.kanbanStateBIReporter.reportDragStart({
                itemId: keyedItem.id,
                itemIndex: keyedItem.index,
                stageId,
                dragAndDropID: this._moveId,
            });
        };
        this.handleDragCancel = () => {
            this.status = 'cancel';
            this.setActiveId(null);
        };
        this.handleDragEnd = async (event) => {
            this.status = 'end';
            const { active, over } = event;
            this.setActiveId(null);
            if (!over) {
                return;
            }
            const activeId = active.id.toString();
            const overId = over.id.toString();
            const fromStageId = this._findStageByItemId(activeId);
            // Determine target stage - could be stage key directly or extracted from item ID
            let toStageId;
            if (this.kanbanState.kanbanStageStates[overId]) {
                // Dropping on a stage background
                toStageId = overId;
            }
            else {
                // Dropping on an item - extract stage from item ID
                toStageId = this._findStageByItemId(overId);
            }
            // Only return early if we don't have valid source and target stages
            if (!fromStageId || !toStageId) {
                return;
            }
            // PREVENT MOVEMENT WITHIN THE SAME STAGE
            if (fromStageId === toStageId) {
                return; // Don't allow reordering within the same stage
            }
            const keyedItem = this._findItemById(activeId);
            const item = keyedItem?.item;
            if (!item) {
                return;
            }
            // Create the Kanban drag end event
            const kanbanDragEndEvent = {
                item,
                fromStage: this.kanbanState.getStageById(fromStageId),
                toStage: this.kanbanState.getStageById(toStageId),
            };
            if (this.kanbanState.items?.dragAndDrop?.onSubmit) {
                const originalItem = item;
                const updatedItem = {
                    ...item,
                    [this.kanbanState.items.stageField]: toStageId,
                };
                try {
                    this.kanbanState.moveItemBetweenStages(originalItem, updatedItem, fromStageId, toStageId);
                    const submittedItem = await this.kanbanState.items.dragAndDrop.onSubmit(kanbanDragEndEvent);
                    const submittedItemStageId = submittedItem[this.kanbanState.items.stageField];
                    if (toStageId !== submittedItemStageId) {
                        // move has been cancelled
                        this.kanbanState.moveItemBetweenStages(updatedItem, originalItem, toStageId, fromStageId);
                        this.kanbanState.kanbanStateBIReporter.reportDragEnd({
                            itemId: keyedItem.id,
                            itemIndexBefore: keyedItem.index,
                            itemIndexAfter: keyedItem.index,
                            stageIdBefore: fromStageId,
                            stageIdAfter: fromStageId,
                            dragAndDropID: this._moveId,
                            endType: 'drop back',
                        });
                        return;
                    }
                    this.kanbanState.updateCard(submittedItem);
                    this.kanbanState.kanbanStateBIReporter.reportDragEnd({
                        itemId: keyedItem.id,
                        itemIndexBefore: keyedItem.index,
                        itemIndexAfter: 0,
                        stageIdBefore: fromStageId,
                        stageIdAfter: toStageId,
                        dragAndDropID: this._moveId,
                        endType: 'drop succeeded',
                    });
                }
                catch (error) {
                    // rollback the move
                    this.kanbanState.moveItemBetweenStages(updatedItem, originalItem, toStageId, fromStageId);
                    this.kanbanState.kanbanStateBIReporter.reportDragEnd({
                        itemId: keyedItem.id,
                        itemIndexBefore: keyedItem.index,
                        itemIndexAfter: keyedItem.index,
                        stageIdBefore: fromStageId,
                        stageIdAfter: fromStageId,
                        dragAndDropID: this._moveId,
                        endType: 'drag disabled',
                    });
                    this.kanbanState.showErrorToast(error);
                }
            }
        };
        this.kanbanState = params.kanbanState;
        makeObservable(this, {
            handleDragEnd: action,
            setActiveId: action,
            activeId: observable,
            status: observable.ref,
            handleDragStart: action,
            handleDragCancel: action,
        });
    }
    _parseItemId(combinedId) {
        // Parse combined ID format: "stageKey-##-itemKey"
        const [stageKey, itemKey] = combinedId.split('-##-');
        if (!stageKey || !itemKey) {
            return null;
        }
        return { stageKey, itemKey };
    }
    _findItemById(combinedId) {
        const parsed = this._parseItemId(combinedId);
        if (!parsed) {
            return null;
        }
        const stageState = this.kanbanState.kanbanStageStates[parsed.stageKey];
        if (!stageState) {
            return null;
        }
        const item = stageState.itemsCollectionState.getKeyedItem(parsed.itemKey);
        return item || null;
    }
    _findStageByItemId(combinedId) {
        const parsed = this._parseItemId(combinedId);
        return parsed?.stageKey || null;
    }
    init() {
        // No initialization needed for native drag and drop
    }
    get keyboardCodes() {
        return {
            start: ['Space', 'Enter'],
            cancel: ['Escape'],
            end: ['Space', 'Enter'],
        };
    }
}
export const KanbanCardDragAndDrop = {
    KanbanDragAndDropContext,
    DraggableCard: KanbanDraggableCardItem,
    DragOverlay: KanbanDragOverlay,
};
//# sourceMappingURL=KanbanCardDragAndDrop.js.map