import { BasePage } from '@/manager/shared/base/BasePage';
import { BookingDetailsAdjustmentNotificationCard } from '@/manager/modules/booking/components/BookingDetailsAdjustmentNotificationCard';
import { BookingDetailsBillingCard } from '@/manager/modules/booking/components/BookingDetailsBillingCard';
import { BookingDetailsGeneralCard } from '@/manager/modules/booking/components/BookingDetailsGeneralCard';
import { BookingDetailsInvoicesCard } from '@/manager/modules/booking/components/BookingDetailsInvoicesCard';
import { BookingDetailsItemsCard } from '@/manager/modules/booking/components/BookingDetailsItemsCard';
import { BookingDetailsNotesCard } from '@/manager/modules/booking/components/BookingDetailsNotesCard';
import { BookingDetailsPaymentsCard } from '@/manager/modules/booking/components/BookingDetailsPaymentsCard';
import { BookingAdjustmentDialog } from '@/manager/modules/booking/views/BookingAdjustmentDialog';
import { BookingAdjustmentDeleteDialog } from '@/manager/modules/booking/views/BookingAdjustmentDeleteDialog';
import { BookingAdjustMoveInDateDialog } from '@/manager/modules/booking/views/BookingAdjustMoveInDateDialog';
import { BookingCancelDialog } from '@/manager/modules/booking/views/BookingCancelDialog';
import { BookingCancelRevokeDialog } from '@/manager/modules/booking/views/BookingCancelRevokeDialog';
import { BookingEditNotesDialog } from '@/manager/modules/booking/views/BookingEditNotesDialog';
import { BookingRemovePriceChangeDialog } from '@/manager/modules/booking/views/BookingRemovePriceChangeDialog';
import { BookingUpdatePaymentMethodDialog } from '@/manager/modules/booking/views/BookingUpdatePaymentMethodDialog';
import { BookingListPage } from '@/manager/modules/booking/views/BookingListPage';
import { getPageHeaderStatusHost, getPageHeaderBackButtonHost } from '@/manager/shared/utils/locator-utils';
import { getDetailsPageIdFromUrl } from '@/manager/shared/utils/url-utils';

export class BookingDetailsPage extends BasePage {
  readonly baseStatus = getPageHeaderStatusHost(this.header);
  readonly cancelsOnStatus = this.header.getByTestId('base-view-header-status-cancels-on');
  readonly canceledBeforeStartStatus = this.header.getByTestId('base-view-header-status-canceled-before-start');
  readonly backButton = getPageHeaderBackButtonHost(this.header);
  readonly actionMenu = this.host.getByTestId('booking-action-menu');
  readonly actionMenuButton = this.header.getByTestId('booking-action-button');
  readonly actionMenuCancelBookingItem = this.actionMenu.getByTestId('booking-action-cancel-booking');
  readonly actionMenuCancelRescheduleBookingItem = this.actionMenu.getByTestId(
    'booking-action-reschedule-cancellation'
  );
  readonly actionMenuCancelRevokeBookingItem = this.actionMenu.getByTestId('booking-action-revert-cancel');
  readonly actionMenuRemovePriceChangeItem = this.actionMenu.getByTestId('booking-action-remove-price-change');
  readonly actionMenuAdjustMoveInDateItem = this.actionMenu.getByTestId('booking-action-adjust-move-in');
  readonly actionMenuUpdatePaymentMethodItem = this.actionMenu.getByTestId('booking-action-update-payment');
  readonly actionMenuAdjustItem = this.actionMenu.getByTestId('booking-action-adjust');
  readonly actionMenuDeleteAdjustmentItem = this.actionMenu.getByTestId('booking-action-delete');
  readonly adjustmentNotificationCard = new BookingDetailsAdjustmentNotificationCard(this.body);
  readonly generalCard = new BookingDetailsGeneralCard(this.body);
  readonly notesCard = new BookingDetailsNotesCard(this.body);
  readonly billingCard = new BookingDetailsBillingCard(this.body);
  readonly itemsCard = new BookingDetailsItemsCard(this.body);
  readonly invoicesCard = new BookingDetailsInvoicesCard(this.body);
  readonly paymentsCard = new BookingDetailsPaymentsCard(this.body);

  async goto(id: number): Promise<void> {
    await this.host.goto(`/bookings/${id}`);
  }

  async openBookingCancelDialog(): Promise<BookingCancelDialog> {
    await this.actionMenuButton.click();
    await this.actionMenuCancelBookingItem.click();
    return new BookingCancelDialog(this.host, false);
  }

  async openBookingCancelRescheduleDialog(): Promise<BookingCancelDialog> {
    await this.actionMenuButton.click();
    await this.actionMenuCancelRescheduleBookingItem.click();
    return new BookingCancelDialog(this.host, true);
  }

  async openBookingCancelRevokeDialog(): Promise<BookingCancelRevokeDialog> {
    await this.actionMenuButton.click();
    await this.actionMenuCancelRevokeBookingItem.click();
    return new BookingCancelRevokeDialog(this.host);
  }

  async openBookingAdjustMoveInDateDialog(): Promise<BookingAdjustMoveInDateDialog> {
    await this.actionMenuButton.click();
    await this.actionMenuAdjustMoveInDateItem.click();
    return new BookingAdjustMoveInDateDialog(this.host);
  }

  async openBookingUpdatePaymentMethodDialog(): Promise<BookingUpdatePaymentMethodDialog> {
    await this.actionMenuButton.click();
    await this.actionMenuUpdatePaymentMethodItem.click();
    return new BookingUpdatePaymentMethodDialog(this.host);
  }

  async openBookingAdjustmentDialog(): Promise<BookingAdjustmentDialog> {
    await this.actionMenuButton.click();
    await Promise.all([this.host.waitForURL('**/bookings/*/adjust'), this.actionMenuAdjustItem.click()]);
    return new BookingAdjustmentDialog(this.host);
  }

  async openBookingAdjustmentDialogFromNotification(): Promise<BookingAdjustmentDialog> {
    await Promise.all([
      this.host.waitForURL('**/bookings/*/adjust'),
      this.adjustmentNotificationCard.editButton.click(),
    ]);
    return new BookingAdjustmentDialog(this.host);
  }

  async openBookingAdjustmentDeleteDialog(): Promise<BookingAdjustmentDeleteDialog> {
    await this.actionMenuButton.click();
    await this.actionMenuDeleteAdjustmentItem.click();
    return new BookingAdjustmentDeleteDialog(this.host);
  }

  async openBookingAdjustmentDeleteDialogFromNotification(): Promise<BookingAdjustmentDeleteDialog> {
    await this.adjustmentNotificationCard.deleteButton.click();
    return new BookingAdjustmentDeleteDialog(this.host);
  }

  async openBookingRemovePriceChangeDialog(): Promise<BookingRemovePriceChangeDialog> {
    await this.actionMenuButton.click();
    await this.actionMenuRemovePriceChangeItem.click();
    return new BookingRemovePriceChangeDialog(this.host);
  }

  async openBookingEditNotesDialog(): Promise<BookingEditNotesDialog> {
    await Promise.all([this.host.waitForURL('**/bookings/*/edit/notes'), this.notesCard.editButton.click()]);
    return new BookingEditNotesDialog(this.host);
  }

  getBookingId(): number {
    return getDetailsPageIdFromUrl(this.host.url(), 'bookings');
  }

  async returnToBookingListPage(): Promise<BookingListPage> {
    await Promise.all([this.host.waitForURL('/bookings'), this.backButton.click()]);
    return new BookingListPage(this.host);
  }
}
