import * as React from 'react';
import { AddItem, Box, CounterBadge, Text } from '@wix/design-system';
import { FiltersMap, KeyedItem } from '@wix/bex-core';
import { observer } from 'mobx-react-lite';
import { CardComponent, KanbanCardProps } from './Card';
import { KanbanBaseProps } from './KanbanProps';
import { KanbanCardDragAndDrop } from '../KanbanDragAndDropDndKit/KanbanCardDragAndDrop';
import { ItemActionsState } from '../../state';
import { useDroppable } from '@wix/wix-style-react-incubator/dnd-kit/core';
import { KanbanState } from '../../state/KanbanState';
import { action } from 'mobx';
import { CardsSkeleton } from './CardsSkeleton';
import { useEffect } from 'react';
import { StageActions } from './StageActions';

interface StageComponentProps<T, S, F extends FiltersMap> {
  dataHook: string;
  state: KanbanState<T, S, F>;
  stageSummary?: KanbanBaseProps<T, S, F>['stageSummary'];
  renderItem?: KanbanBaseProps<T, S, F>['renderItem'];
  noResultsState?: KanbanBaseProps<T, S, F>['noResultsState'];
  actionCell?: KanbanBaseProps<T, S, F>['actionCell'];
  dataExtension?: KanbanBaseProps<T, S, F>['dataExtension'];
  tags?: KanbanBaseProps<T, S, F>['tags'];
  activeStageKey?: string | null; // Active source stage key
  stageActionCell?: KanbanBaseProps<T, S, F>['stageActionCell'];
  stageKey: string;
}

function _StageComponent<T, S, F extends FiltersMap>({
  dataHook,
  state,
  stageSummary,
  activeStageKey,
  stageKey,
  stageActionCell,
  ...props
}: StageComponentProps<T, S, F>) {
  const stageState = state.kanbanStageStates[stageKey];
  const { events } = state;
  const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
    const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
    if (
      scrollHeight - scrollTop <= clientHeight + 10 &&
      !stageState.itemsCollectionState.fetchedLastPage &&
      !stageState.itemsCollectionState.result.status.isFetching
    ) {
      stageState.fetchMore();
    }
  };

  const {
    result: { keyedItems },
    status,
  } = stageState.itemsCollectionState;

  useEffect(() => {
    if (stageState.hasError) {
      stageState.showErrorToast(status.error);
    }
  }, [stageState.hasError]);

  const scrollToCardInStage = ({
    stageKey: _stageKey,
    cardKey,
  }: {
    stageKey: string;
    cardKey: string;
  }) => {
    if (stageKey !== stageState.stageKey) {
      return;
    }
    const cardElement = document.querySelector(
      `[data-hook="kanban-card-container-${_stageKey}-${cardKey}"]`,
    );
    if (cardElement) {
      cardElement.scrollIntoView?.({
        behavior: 'smooth',
        block: 'nearest',
        inline: 'nearest',
      });
    }
  };

  useEffect(() => {
    events.on('scrollToCardInStage', scrollToCardInStage);

    return () => {
      events.off('scrollToCardInStage', scrollToCardInStage);
    };
  }, [events, stageKey]);

  // Make the stage droppable
  const { isOver, setNodeRef: setDroppableRef } = useDroppable({
    id: stageState.stageKey,
  });

  // Check if this stage is the source stage (where drag originated)
  const isDndSourceStage = activeStageKey === stageState.stageKey;

  const items: KanbanCardProps<T, S, F>[] = React.useMemo(() => {
    return keyedItems.map((keyedItem: KeyedItem<T>, index: number) => {
      const itemActionsState = new ItemActionsState({
        fade: 'static',
        keyedItem,
        collection: stageState.itemsCollectionState,
        reportBi: state.toolbar.reportBi,
      });

      return {
        keyedItem,
        stageKey: stageState.stageKey,
        originalItem: keyedItem.item,
        itemIndex: index,
        itemActionsState,
        item: {
          ...props.renderItem?.({
            stage: stageState.stage,
            item: keyedItem.item,
          }),
          key: keyedItem.key,
        },
        actionCell: props.actionCell,
        state,
      };
    });
  }, [keyedItems, keyedItems.length]);

  const { DraggableCard } = KanbanCardDragAndDrop;
  const isInSearchMode = state.isInSearchMode();
  const isInFilterMode = state.isInFilterMode();
  const isStageLoading = stageState.isLoading;
  const isChangingFiltersValue = state.getIsChangingFiltersValue();
  const shouldShowStageSummary = !isChangingFiltersValue && !isStageLoading;
  return (
    <div
      ref={setDroppableRef}
      data-hook={`kanban-stage-container-${stageState.stageKey}`}
      style={{
        width: '270px',
        backgroundColor: isOver && !isDndSourceStage ? '#D6E6FE' : '#F4F7FF',
        borderRadius: '8px',
        display: 'flex',
        flexDirection: 'column',
        border:
          isOver && !isDndSourceStage
            ? '1px dashed #80B1FF'
            : '1px solid transparent',
      }}
      {...(process.env.NODE_ENV === 'test' && {
        onPointerUp: action(() => {
          if (state.dragAndDropState.activeId) {
            state.dragAndDropState.handleDragEnd({
              over: { id: stageState.stageKey },
              active: { id: state.dragAndDropState.activeId },
            } as any);
          }
        }),
      })}
    >
      <Box width="270px" direction="vertical">
        <div data-hook={dataHook}>
          <Box direction="vertical" padding="12px">
            <Box
              marginBottom="24px"
              direction="vertical"
              padding="0px 6px 0 6px"
              borderRadius="8px"
            >
              <Box direction="horizontal" align="space-between">
                <Box gap="SP1" maxWidth="200px">
                  <Text
                    ellipsis
                    size="small"
                    weight="bold"
                    dataHook={`kanban-stage-title-${stageState.stageKey}`}
                  >
                    {stageState.stageName}
                  </Text>

                  {shouldShowStageSummary && (
                    <CounterBadge
                      dataHook={`kanban-stage-title-total-${stageState.stageKey}`}
                      skin="light"
                      truncate={false}
                    >
                      {stageState.totalItems}
                    </CounterBadge>
                  )}
                </Box>

                {stageActionCell && (
                  <StageActions
                    state={state}
                    stageKey={stageState.stageKey}
                    stageActionCell={stageActionCell}
                  />
                )}
              </Box>

              <Box gap="0.2em">
                {shouldShowStageSummary ? (
                  <Text size="tiny" weight="thin">
                    {stageSummary?.({ stage: stageState.stage })}
                  </Text>
                ) : null}
              </Box>
            </Box>
            {shouldShowStageSummary && state.items.create?.title ? (
              <Box>
                <AddItem
                  size="tiny"
                  removePadding={true}
                  dataHook={`kanban-stage-add-card-${stageState.stageKey}`}
                  onClick={() => {
                    state.items.create?.navigateToEntityPage?.({
                      stage: stageState.stage,
                    });
                    state.kanbanStateBIReporter.reportStageCTAClicked({
                      ctaName: 'Add Card',
                      ctaType: 'Primary Button',
                      stageId: stageState.stageKey,
                      stageIndex: state.getStageIndexByKey(stageState.stageKey),
                      stageName: stageState.stageName,
                    });
                  }}
                >
                  <Box paddingTop="9px" paddingBottom="9px">
                    {state.items.create?.title}
                  </Box>
                </AddItem>
              </Box>
            ) : null}
          </Box>
          {state.isRefetching || isStageLoading || isChangingFiltersValue ? (
            <CardsSkeleton stageKey={stageState.stageKey} />
          ) : (
            <Box paddingBottom="12px" direction="vertical">
              <div
                data-hook={`kanban-stage-cards-container-${stageState.stageKey}`}
                style={{
                  overflow: 'auto',
                  minHeight: '430px',
                  height: 'calc(100vh - 420px)',
                  display: 'flex',
                  flexDirection: 'column',
                  gap: '12px',
                  alignItems: 'center',
                  overflowX: 'hidden',
                  scrollbarWidth: 'thin',
                  scrollbarColor: '#CFD1DC transparent',
                  paddingTop: '3px',
                }}
                onScroll={handleScroll}
              >
                {(isInSearchMode || isInFilterMode) && items.length === 0 ? (
                  <Box
                    flex="1"
                    verticalAlign="middle"
                    dataHook={`kanban-stage-no-results-${stageState.stageKey}`}
                  >
                    {props.noResultsState}
                  </Box>
                ) : (
                  items?.map((item) => (
                    <DraggableCard
                      key={`${item.stageKey}-##-${item.item.key}`}
                      id={`${item.stageKey}-##-${item.item.key}`}
                      state={state}
                      cardProps={{
                        keyedItem: item.keyedItem,
                        originalItem: item.keyedItem.item,
                        itemIndex: item.itemIndex,
                        item: item.item,
                        stageKey: item.stageKey,
                        actionCell: item.actionCell,
                        itemActionsState: item.itemActionsState,
                        dataExtension: props.dataExtension,
                        tags: props.tags,
                        state,
                      }}
                    >
                      {CardComponent}
                    </DraggableCard>
                  ))
                )}
                {stageState.itemsCollectionState.status.isLoading && (
                  <div className="text-sm text-center text-gray-500">
                    Loading more...
                  </div>
                )}
              </div>
            </Box>
          )}
        </div>
      </Box>
    </div>
  );
}

export const StageComponent = observer(_StageComponent);
