import { DataCapsule, TaskState, WixPatternsContainer } from '@wix/bex-core';
import { ColumnSizesService } from '../services';
import { makeObservable, observable, runInAction } from 'mobx';
import { Column } from '../model';

export interface ColumnSizesStateParams {
  dataCapsule: DataCapsule;
  container: WixPatternsContainer;
  fqdn: string;
}

export class ColumnSizesState {
  private readonly columnSizeService: ColumnSizesService;
  private readonly container: WixPatternsContainer;

  readonly isResizeExperimentEnabled: boolean;
  readonly initTask = new TaskState();
  columnWidths: Record<string, number> | undefined = undefined;

  constructor(params: ColumnSizesStateParams) {
    this.container = params.container;
    this.isResizeExperimentEnabled =
      this.container.internalExperiments?.enabled(
        'specs.cairo.ResizeColumns',
      ) ?? false;

    this.columnSizeService = new ColumnSizesService({
      fqdn: params.fqdn,
      storage: params.dataCapsule,
      errorHandler: params.container.errorHandler,
    });

    makeObservable(this, {
      columnWidths: observable.ref,
      isResizeExperimentEnabled: observable,
    });
  }

  init() {
    if (!this.isResizeExperimentEnabled) {
      return;
    }

    this.initTask.runOnce(async () => {
      const data = await this.columnSizeService.fetchColumnSizes();
      runInAction(() => {
        this.columnWidths = data?.columnWidths;
      });
    });
  }

  mergeSizes(baseColumns: Column[]) {
    if (!this.isResizeExperimentEnabled) {
      return baseColumns;
    }

    const merged = baseColumns.map((column) => {
      const persistedWidth = column.id
        ? this.columnWidths?.[column.id]
        : undefined;
      return persistedWidth ? { ...column, width: persistedWidth } : column;
    });

    return merged;
  }

  async updateColumnWidth(columnId: string, width: number) {
    const oldColumnWidths = { ...this.columnWidths };
    const newColumnWidths = {
      ...oldColumnWidths,
      [columnId]: width,
    };

    runInAction(() => {
      this.columnWidths = newColumnWidths;
    });

    try {
      await this.columnSizeService.updateColumnWidths(newColumnWidths);
    } catch (error) {
      const resolvedError =
        this.container.errorHandler?.getResolvedError?.(error);
      this.container?.showToast?.({
        biName: 'cairo-column-sizes-update-error',
        message: resolvedError?.message!,
        type: 'ERROR',
      });
    }
  }
}
