import {
  CollectionState,
  FiltersMap,
  SelectState,
  TransitionState,
  WixPatternsContainer,
} from '@wix/bex-core';
import { action, computed, makeObservable, observable } from 'mobx';
import { Column } from '../model';
import { CustomColumnsActionName } from './CustomColumnsState';
import type { CustomColumnsDragAndDropState } from './CustomColumnsDragAndDropState';
import type { CollectionDataExtensionState } from '../components/DataExtension';

export interface CustomColumnsPanelStateBaseParams {
  container: WixPatternsContainer;
  queryName: string;
}

export abstract class CustomColumnsPanelStateBase<
  T = unknown,
  F extends FiltersMap = FiltersMap,
> {
  readonly container: WixPatternsContainer;
  readonly columnsCollection: CollectionState<Column, FiltersMap>;

  readonly select = new SelectState<{ id: string }>({
    keyGetter: (column) => column.id,
  });

  searchValue = '';

  onColumnClick?: (column: Column, checked: boolean) => unknown;

  constructor(params: CustomColumnsPanelStateBaseParams) {
    this.container = params.container;

    this.columnsCollection = new CollectionState({
      ...this.container,
      events: {},
      queryName: params.queryName,
      fetchData: async () => {
        const items = this.filteredColumns.filter(
          (column) => column.hiddenFromCustomColumnsSelection !== true,
        );
        return { items };
      },
      filters: {},
      itemKey: (item) => item.id,
      itemName: (item) => item.name,
    });
  }

  protected initBaseObservables() {
    makeObservable(this, {
      searchValue: observable,
      setSearchValue: action.bound,
      orderedColumns: computed,
      filteredColumns: computed,
    });
  }

  abstract get orderedColumns(): Column[];

  abstract get showFieldTypeIcons(): boolean;

  abstract get collectionDataExtension():
    | CollectionDataExtensionState<T, F>
    | null
    | undefined;

  abstract get sidePanelTransition(): TransitionState<string> | undefined;

  abstract get dragAndDrop(): CustomColumnsDragAndDropState<T, F> | undefined;

  abstract customizeColumnsInSidePanelBi(params: {
    actionName: CustomColumnsActionName;
  }): void;

  abstract onClose(): void;

  abstract init(): () => void;

  get filteredColumns(): Column[] {
    const { orderedColumns, searchValue } = this;

    if (!searchValue.trim()) {
      return orderedColumns;
    }

    const searchLower = searchValue.toLowerCase();
    return orderedColumns.filter((column) => {
      const name =
        column.name ||
        (typeof column.title === 'string' ? column.title : column.id);
      return name.toLowerCase().includes(searchLower);
    });
  }

  setSearchValue = action((value: string) => {
    this.searchValue = value;
    this.columnsCollection.refreshAllPages();
  });

  onColumnCheckboxToggle = action((column: Column) => {
    const { select, onColumnClick } = this;
    select.toggle(column);
    onColumnClick?.(column, select.isChecked(column.id));
  });
}
