import { BaseDialog } from '@/manager/shared/base/BaseDialog';
import { DiscountProductList } from '@/manager/modules/discount/components/DiscountProductList';
import { DiscountProductSelection, DiscountUpdateProductsData } from '@/manager/modules/discount/discount-types';
import { getSnackbarHost } from '@/manager/shared/utils/locator-utils';
import { Page } from '@playwright/test';

export class DiscountEditProductsDialog extends BaseDialog {
  readonly list = new DiscountProductList(this.main);
  readonly updatedSnackbar = getSnackbarHost(this.host, 'Discount successfully updated');
  readonly notEmptySnackbar = getSnackbarHost(this.host, 'Please provide at least one booking plan or product.');
  readonly codeInUseSnackbar = getSnackbarHost(this.host, 'Code already in use');

  constructor(
    host: Page,
    readonly showAlerts: boolean
  ) {
    super(host, 'discount-edit-products-dialog');
  }

  async deselectAll(): Promise<void> {
    await this.list.dataTable.selectRowsPerPage(100);
    await this.list.dataTable.rowSelector.deselectAll();
  }

  async select(selection: DiscountProductSelection): Promise<void> {
    await this.toggle(selection, true);
    await this.submitAndConfirm();
  }

  async update(changes: DiscountUpdateProductsData): Promise<void> {
    await this.applyUpdate(changes);
    await this.submitAndConfirm();
  }

  async applyUpdate(changes: DiscountUpdateProductsData): Promise<void> {
    await this.toggle(changes.attach ?? {}, true);
    await this.toggle(changes.detach ?? {}, false);
  }

  async submit(): Promise<void> {
    await this.submitButton.click();
  }

  private async submitAndConfirm(): Promise<void> {
    const waits: Promise<unknown>[] = [this.submit()];

    if (this.showAlerts) {
      waits.unshift(this.updatedSnackbar.waitFor());
    }

    await Promise.all(waits);
  }

  private async toggle(selection: DiscountProductSelection, select: boolean): Promise<void> {
    for (const product of selection.products ?? []) {
      await this.searchAndToggle(product.name, select);
    }

    for (const deposit of selection.deposits ?? []) {
      await this.searchAndToggle(deposit.name, select);
    }
  }

  private async searchAndToggle(name: string, select: boolean): Promise<void> {
    await this.list.searchTextField.fill(name);
    return select ? this.list.dataTable.rowSelector.select(0) : this.list.dataTable.rowSelector.deselect(0);
  }
}
