import { CollectionState, FiltersMap } from '@wix/bex-core';
import { computed, makeObservable, observable } from 'mobx';
import { GridState, ToolbarCollectionState } from '../../state';
import type {
  Section,
  GroupBy,
  RenderSection,
} from '../CollectionSectionHeader';

export interface SectionRange {
  sectionId: string;
  sectionIndex: number;
  section: Section;
  range: {
    start: number;
    length: number;
  };
}

export interface GridSectionsStateParams<T, F extends FiltersMap> {
  readonly collection: CollectionState<T, F>;
  readonly toolbar: ToolbarCollectionState<T, F>;
  readonly groupBy: GroupBy<T>;
  readonly renderSection?: RenderSection<T>;
  readonly parentState: GridState<T, F>;
}

export class GridSectionsState<T, F extends FiltersMap> {
  groupBy: GroupBy<T>;
  renderSection?: RenderSection<T>;
  readonly toolbar;
  readonly collection;
  readonly parentState;

  constructor(params: GridSectionsStateParams<T, F>) {
    this.collection = params.collection;
    this.toolbar = params.toolbar;
    this.groupBy = params.groupBy;
    this.renderSection = params.renderSection;
    this.parentState = params.parentState;

    makeObservable(this, {
      sections: computed,
      groupBy: observable.ref,
      renderSection: observable.ref,
    });
  }

  get sections(): SectionRange[] {
    const { collection, groupBy, renderSection } = this;

    if (!groupBy) {
      return [];
    }

    const sectionItemsMap: Record<string, T[]> = {};
    const orderedSections: string[] = [];

    collection.result.items.forEach((item) => {
      const sectionId = groupBy(item);

      if (!sectionItemsMap[sectionId]) {
        sectionItemsMap[sectionId] = [];
        orderedSections.push(sectionId);
      }
      sectionItemsMap[sectionId].push(item);
    });

    let currentIndex = 0;
    return orderedSections.map((sectionId, sectionIndex) => {
      const sectionItems = sectionItemsMap[sectionId];

      const section = renderSection
        ? renderSection(sectionId, sectionItems)
        : { title: sectionId };

      const range = {
        start: currentIndex,
        length: sectionItems.length,
      };

      currentIndex += sectionItems.length;

      return { sectionId, sectionIndex, section, range };
    });
  }
}
