import { FiltersMap, withoutDefaults } from '@wix/bex-core';
import {
  loadEnd,
  cairoFilterToggled,
  cairoSearchResults,
  cairoCtaClicked,
  cairoDragItem,
  cairoDragItemEndDrop,
} from '@wix/bex-core/bi';
import { runInAction } from 'mobx';
import { KanbanComponentType, type KanbanState } from './KanbanState';

export enum KanbanCtaType {
  PRIMARY_BUTTON = 'Primary Button',
  SECONDARY_DROPDOWN = 'Secondary Dropdown',
  MORE_ACTIONS_OPTION = 'More Actions Option',
}

export class KanbanStateBIReporter<T, S, F extends FiltersMap> {
  readonly kanbanState: KanbanState<T, S, F>;
  appLoaded?: () => void;
  private _startTime: number;

  constructor(kanbanState: KanbanState<T, S, F>) {
    this.kanbanState = kanbanState;
    this._startTime = performance.now();
  }

  get reportBi() {
    return this.kanbanState.container.reportBi;
  }

  get toolbar() {
    return this.kanbanState.toolbar;
  }

  init() {
    // Set up callback for when app loading is complete
    this.appLoaded = () => {
      this.reportOnLoadEnd(Math.round(performance.now() - this._startTime));
    };
  }

  // 144:111
  reportOnLoadEnd(loadingTime: number) {
    this.reportBi({
      ...withoutDefaults(loadEnd)({
        ...this.toolbar._commonDynamicBiParams(),
      }),
      params: {
        ...this.toolbar._commonDynamicBiParams(),
        componentType: KanbanComponentType,
        componentStatus: 'Kanban',
        currentKanban: this.kanbanState.kanbanId,
        filteredListSize: this.getTotalCardsCount(),
        stageCardCnt: this.getStageCardCounts(),
        loadingTime,
      },
    });
  }

  reportSearchTriggered = (searchTerm: string) => {
    const startTime = performance.now();

    // 144:117
    this.reportBi({
      ...withoutDefaults(cairoFilterToggled)({
        ...this.toolbar._commonDynamicBiParams(),
      }),
      params: {
        ...this.toolbar._commonDynamicBiParams(),
        componentType: KanbanComponentType,
        filterName: 'search',
        filterValue: searchTerm,
        origin: 'toolbar',
        filteredListSize: this.getTotalCardsCount(),
        numFiltersActive: this.kanbanState.query.activeFiltersCount,
        actionType: 'add',
        kanbanId: this.kanbanState.kanbanId,
      },
    });

    return () => {
      const searchResultsCount = this.getTotalCardsCount();
      // 144:116
      this.reportBi({
        ...withoutDefaults(cairoSearchResults)({
          ...this.toolbar._commonDynamicBiParams(),
          searchResultsCnt: searchResultsCount,
        }),
        params: {
          ...this.toolbar._commonDynamicBiParams(),
          componentType: KanbanComponentType,
          searchResultsCnt: searchResultsCount,
          stageCardCnt: this.getStageCardCounts(),
          searchTerm,
          loadingTime: Math.round(performance.now() - startTime),
          kanbanId: this.kanbanState.kanbanId,
        },
      });
    };
  };

  // 144:138
  reportDragStart = ({
    itemId,
    itemIndex,
    stageId,
    dragAndDropID,
  }: {
    itemId: string;
    itemIndex: number;
    stageId: string;
    dragAndDropID: string;
  }) => {
    this.reportBi({
      ...withoutDefaults(cairoDragItem)({
        ...this.toolbar._commonDynamicBiParams(),
      }),
      params: {
        ...this.toolbar._commonDynamicBiParams(),
        componentType: KanbanComponentType,
        itemId,
        itemIndex,
        itemLevel: this.kanbanState.getStageIndexByKey(stageId),
        hierarchyPathIndex: null,
        dragAndDropID,
        stageType: this.getStageType(stageId) === 'DONE' ? 'done' : 'regular',
        kanbanId: this.kanbanState.kanbanId,
      },
    });
  };

  // 144:139
  reportDragEnd = ({
    itemId,
    itemIndexBefore,
    itemIndexAfter,
    stageIdBefore,
    stageIdAfter,
    dragAndDropID,
    endType,
  }: {
    itemId: string;
    itemIndexBefore: number;
    itemIndexAfter: number;
    stageIdBefore: string;
    stageIdAfter: string;
    dragAndDropID: string;
    endType: 'drop succeeded' | 'drop back' | 'drag disabled';
  }) => {
    this.reportBi({
      ...withoutDefaults(cairoDragItemEndDrop)({
        ...this.toolbar._commonDynamicBiParams(),
      }),
      params: {
        ...this.toolbar._commonDynamicBiParams(),
        componentType: KanbanComponentType,
        itemId,
        itemIndexBefore,
        itemIndexAfter,
        itemLevelBefore: this.kanbanState.getStageIndexByKey(stageIdBefore),
        itemLevelAfter: this.kanbanState.getStageIndexByKey(stageIdAfter),
        dragAndDropID,
        stageTypeBefore:
          this.getStageType(stageIdBefore) === 'DONE' ? 'done' : 'regular',
        stageTypeAfter:
          this.getStageType(stageIdAfter) === 'DONE' ? 'done' : 'regular',
        kanbanId: this.kanbanState.kanbanId,
        endType,
      },
    });
  };

  // 144:115
  reportStageCTAClicked = ({
    ctaName,
    ctaType,
    stageId,
    stageIndex,
    stageName,
  }: {
    ctaName: string;
    ctaType: 'Primary Button' | 'Secondary Dropdown';
    stageId: string;
    stageIndex: number;
    stageName: string;
  }) => {
    this.reportBi({
      ...withoutDefaults(cairoCtaClicked)({
        ...this.toolbar._commonDynamicBiParams(),
      }),
      params: {
        ...this.toolbar._commonDynamicBiParams(),
        componentType: KanbanComponentType,
        ctaName,
        ctaType,
        location: 'stage',
        stageId,
        stageIndex,
        stageName,
        kanbanId: this.kanbanState.kanbanId,
      },
    });
  };

  // 144:115
  reportCardCTAClicked = ({
    itemId,
    itemIndex,
    ctaName,
    ctaType,
    ctaIndex,
    numCtas,
    stageId,
    stageIndex,
    stageName,
  }: {
    itemId: string;
    itemIndex: number;
    ctaName: string;
    ctaType: KanbanCtaType;
    ctaIndex?: number;
    numCtas?: number;
    stageId: string;
    stageIndex: number;
    stageName: string;
  }) => {
    this.reportBi({
      ...withoutDefaults(cairoCtaClicked)({
        ...this.toolbar._commonDynamicBiParams(),
      }),
      params: {
        ...this.toolbar._commonDynamicBiParams(),
        componentType: KanbanComponentType,
        itemId,
        itemIndex,
        ctaName,
        ctaType,
        location: 'card',
        stageIndex,
        stageId,
        stageName,
        kanbanId: this.kanbanState.kanbanId,
        ...(ctaIndex !== undefined && { ctaIndex }),
        ...(numCtas !== undefined && { numCtas }),
      },
    });
  };

  private getTotalCardsCount(): number {
    return runInAction(() =>
      Object.values(this.kanbanState.kanbanStageStates).reduce(
        (total, stageState) => total + (stageState?.totalItems || 0),
        0,
      ),
    );
  }

  private getStageCardCounts(): string {
    const counts: Record<string, number> = {};
    runInAction(() => {
      Object.entries(this.kanbanState.kanbanStageStates).forEach(
        ([stageId, stageState]) => {
          if (stageState) {
            counts[stageId] = stageState.totalItems || 0;
          }
        },
      );
    });
    return JSON.stringify(counts);
  }

  private getStageType(stageId: string): string {
    const stage = this.kanbanState.stages.find(
      (s) => this.kanbanState.stageKey(s) === stageId,
    );
    if (!stage) {
      return 'NONE';
    }

    if (this.kanbanState.stageType) {
      return this.kanbanState.stageType(stage) || 'NONE';
    }

    return 'NONE';
  }

  initAdditionalFeaturesAvailability() {
    this.toolbar.featuresAvailability = {
      ...this.toolbar.featuresAvailability,
      isDisablingSearch: false,
      isUsingFilters: this.toolbar.filtersProps
        ? this.toolbar.filtersProps.length > 0
        : false,
      isUsingDragAndDrop: !!this.kanbanState.items.dragAndDrop,
      isUsingBulkActionsToolbar:
        !!this.toolbar.selectionProps.value.showSelection,
      isUsingHorizontalScroll: true,
      isUsingFolders: false,
      isUsingTableVirtualization: false,
      isUsingTags: !!this.toolbar.tagsCollectionState?.Tags,
      isUsingTabs: false,
      isUsingSummaryRow: false,
      isUsingSecondaryActions: true,
      isUsingMoreActions: true,
    };

    this.toolbar.additionalFeaturesAvailability = {
      ...this.toolbar.additionalFeaturesAvailability,
      isUsingTableSubtitle: false,
      isUsingCounterInHeader: false,
      isUsingSelectAllLimitation: false,
      isUsingErrorMessage: !!this.kanbanState.hasStagesError,
      isUsingAllItemsView: true,
      isUsingCustomEmptyState: true,
      isUsingCustomNoResultsState: true,
      isUsingPrimaryActionCta: true,
    };
  }
}
