import { BaseDialog } from '@/manager/shared/base/BaseDialog';
import { DiscountBillingPlanCard } from '@/manager/modules/discount/components/DiscountBillingPlanCard';
import { DiscountCreateCodeFieldSet } from '@/manager/modules/discount/components/DiscountCreateCodeFieldSet';
import { DiscountCreateDurationFieldSet } from '@/manager/modules/discount/components/DiscountCreateDurationFieldSet';
import { DiscountCreateGeneralFieldSet } from '@/manager/modules/discount/components/DiscountCreateGeneralFieldSet';
import { DiscountProductCard } from '@/manager/modules/discount/components/DiscountProductCard';
import { DiscountCreateRestrictionsFieldSet } from '@/manager/modules/discount/components/DiscountCreateRestrictionsFieldSet';
import { DiscountCreateTypeFieldSet } from '@/manager/modules/discount/components/DiscountCreateTypeFieldSet';
import { DiscountCreateData } from '@/manager/modules/discount/discount-types';
import { DiscountDetailsPage } from '@/manager/modules/discount/views/DiscountDetailsPage';
import { getDialogErrorsHost, getSnackbarHost } from '@/manager/shared/utils/locator-utils';
import { getDetailsPageRegExpUrl } from '@/manager/shared/utils/url-utils';
import { Page } from '@playwright/test';

export class DiscountCreateDialog extends BaseDialog {
  readonly generalFieldSet = new DiscountCreateGeneralFieldSet(this.main);
  readonly productCard = new DiscountProductCard(this.main);
  readonly billingPlanCard = new DiscountBillingPlanCard(this.main);
  readonly typeFieldSet = new DiscountCreateTypeFieldSet(this.main);
  readonly durationFieldSet = new DiscountCreateDurationFieldSet(this.main);
  readonly restrictionsFieldSet = new DiscountCreateRestrictionsFieldSet(this.main);
  readonly codeFieldSet = new DiscountCreateCodeFieldSet(this.main);
  readonly errors = getDialogErrorsHost(this.main);
  readonly snackbar = getSnackbarHost(this.host, 'Discount created successfully');

  constructor(host: Page) {
    super(host, 'discount-create-dialog');
  }

  async goto(): Promise<void> {
    await this.host.goto('/discounts/create');
  }

  async create(data: DiscountCreateData): Promise<DiscountDetailsPage> {
    await this.fill(data);
    await Promise.all([
      this.snackbar.waitFor(),
      this.host.waitForURL(getDetailsPageRegExpUrl('discounts')),
      this.submit(),
    ]);
    return new DiscountDetailsPage(this.host);
  }

  async fill(data: DiscountCreateData): Promise<void> {
    await this.generalFieldSet.nameTextField.fill(data.name);
    await this.generalFieldSet.locationAutocomplete.fill(data.location.name);

    const products = data.products ?? [];
    const deposits = data.deposits ?? [];

    if (products.length > 0 || deposits.length > 0) {
      const productDialog = await this.productCard.openDiscountEditProductsDialog(false);
      await productDialog.select({ products, deposits });
    }

    if (data.billingPlans && data.billingPlans.length > 0) {
      const billingPlanDialog = await this.billingPlanCard.openDiscountEditBillingPlansDialog(false);
      await billingPlanDialog.select(data.billingPlans);
    }

    await this.typeFieldSet.typeRadioGroup.check(data.type);
    await this.typeFieldSet.valueNumberField.fill(data.value);

    await this.durationFieldSet.durationRadioGroup.check(data.duration.option);

    if (data.duration.option === 'multiple_months' && data.duration.amount != null) {
      await this.durationFieldSet.multipleMonthsDurationNumberField.fill(data.duration.amount);
    }

    if (data.expirationDate) {
      await this.restrictionsFieldSet.expiryDateCheckbox.set(true);
      await this.restrictionsFieldSet.expiryDateTimePicker.fill(data.expirationDate);
    }

    if (data.usageLimit != null) {
      await this.restrictionsFieldSet.usageLimitCheckbox.set(true);
      await this.restrictionsFieldSet.usageLimitNumberField.fill(data.usageLimit);
    }

    if (data.code.active && data.code.value) {
      await this.codeFieldSet.codeSection.codeSwitch.set(data.code.active);
      await this.codeFieldSet.codeSection.codeTextField.fill(data.code.value);
    }
  }

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