type MutableCurrent<T> = {
  current: T;
};

type MultiSelectInteractionStateLike = {
  isSelecting: boolean;
  startX: number;
  startY: number;
  currentX: number;
  currentY: number;
  selectedAllocationIds: string[];
  selectedResourceIds: string[];
  dateRange: { start: Date; end: Date } | null;
  multiDragDaysDelta: number;
  isMultiDragging: boolean;
  multiDragMode: string;
};

type TimelineDragCleanupParams<
  DragState,
  AllocDragState,
  RangeState,
  MultiSelectState,
  PreviewSession,
> = {
  projectDragCleanupRef: MutableCurrent<(() => void) | null>;
  allocDragCleanupRef: MutableCurrent<(() => void) | null>;
  multiSelectCleanupRef: MutableCurrent<(() => void) | null>;
  projectPreviewRef: MutableCurrent<PreviewSession | null>;
  allocPreviewRef: MutableCurrent<PreviewSession | null>;
  dragStateRef: MutableCurrent<DragState>;
  allocDragRef: MutableCurrent<AllocDragState>;
  rangeStateRef: MutableCurrent<RangeState>;
  multiSelectRef: MutableCurrent<MultiSelectState>;
  initialDragState: DragState;
  initialAllocDragState: AllocDragState;
  initialRangeState: RangeState;
  initialMultiSelectState: MultiSelectState;
  clearPreview: (session: PreviewSession | null) => void;
};

export function cleanupTimelineDragState<
  DragState,
  AllocDragState,
  RangeState,
  MultiSelectState,
  PreviewSession,
>({
  projectDragCleanupRef,
  allocDragCleanupRef,
  multiSelectCleanupRef,
  projectPreviewRef,
  allocPreviewRef,
  dragStateRef,
  allocDragRef,
  rangeStateRef,
  multiSelectRef,
  initialDragState,
  initialAllocDragState,
  initialRangeState,
  initialMultiSelectState,
  clearPreview,
}: TimelineDragCleanupParams<
  DragState,
  AllocDragState,
  RangeState,
  MultiSelectState,
  PreviewSession
>) {
  projectDragCleanupRef.current?.();
  allocDragCleanupRef.current?.();
  multiSelectCleanupRef.current?.();

  projectDragCleanupRef.current = null;
  allocDragCleanupRef.current = null;
  multiSelectCleanupRef.current = null;

  clearPreview(projectPreviewRef.current);
  clearPreview(allocPreviewRef.current);

  projectPreviewRef.current = null;
  allocPreviewRef.current = null;

  dragStateRef.current = initialDragState;
  allocDragRef.current = initialAllocDragState;
  rangeStateRef.current = initialRangeState;
  multiSelectRef.current = initialMultiSelectState;
}

export function cancelTransientMultiSelectState<TState extends MultiSelectInteractionStateLike>(
  state: TState,
  initialState: TState,
): TState {
  const hasCommittedSelection =
    state.selectedAllocationIds.length > 0 || state.selectedResourceIds.length > 0 || state.dateRange !== null;

  if (!hasCommittedSelection) {
    return initialState;
  }

  return {
    ...state,
    isSelecting: false,
    startX: 0,
    startY: 0,
    currentX: 0,
    currentY: 0,
    multiDragDaysDelta: 0,
    isMultiDragging: false,
    multiDragMode: initialState.multiDragMode,
  };
}
