import { BaseDialog } from '@/manager/shared/base/BaseDialog';
import { DiscountBillingPlanList } from '@/manager/modules/discount/components/DiscountBillingPlanList';
import { DiscountUpdateBillingPlansData } from '@/manager/modules/discount/discount-types';
import { DiscountBillingPlan } from '@/shared/types/discount-types';
import { getSnackbarHost } from '@/manager/shared/utils/locator-utils';
import { formatBillingPeriod } from '@/shared/utils/formatters';
import { Page } from '@playwright/test';

export class DiscountEditBillingPlansDialog extends BaseDialog {
  readonly list = new DiscountBillingPlanList(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-billing-plans-dialog');
  }

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

  async select(billingPlans: DiscountBillingPlan[]): Promise<void> {
    for (const billingPlan of billingPlans) {
      await this.searchAndToggle(billingPlan, true);
    }

    await this.submitAndConfirm();
  }

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

  async applyUpdate(changes: DiscountUpdateBillingPlansData): Promise<void> {
    for (const billingPlan of changes.attach ?? []) {
      await this.searchAndToggle(billingPlan, true);
    }

    for (const billingPlan of changes.detach ?? []) {
      await this.searchAndToggle(billingPlan, 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 searchAndToggle(billingPlan: DiscountBillingPlan, select: boolean): Promise<void> {
    const { unitType, plan } = billingPlan;
    await this.list.searchTextField.fill(plan.name ?? '');
    await this.list.unitTypeAutocomplete.fill(unitType.name);
    await this.list.billingPeriodAutocomplete.fill(formatBillingPeriod(plan.period, plan.amount));
    return select ? this.list.dataTable.rowSelector.select(0) : this.list.dataTable.rowSelector.deselect(0);
  }
}
