import { getBookingCancelData, getBookingCreateData } from '@/manager/modules/booking/booking-factories';
import { test } from '@/manager/modules/booking/booking-fixtures';
import { toBookingCancellationDetails } from '@/manager/modules/booking/booking-mappers';
import { bookingCancelHappyTestCases } from '@/manager/modules/booking/test-cases/booking-cancel-happy-test-cases';
import { getCustomerCreateData } from '@/manager/modules/customer/customer-factories';
import {
  expectDataTableChipsColumnToHaveText,
  expectDataTableTextColumnToHaveText,
} from '@/manager/modules/ui/data-table/data-table-assertions';
import { bookingTableColumnTestIds } from '@/manager/modules/ui/data-table/data/data-table-column-test-ids';
import { getUnitCreateData } from '@/manager/modules/unit/unit-factories';
import { getUnitTypeCreateData } from '@/manager/modules/unit-type/unit-type-factories';
import { expectSingleLocatorToHaveText } from '@/manager/shared/utils/expect-utils';
import { formatId } from '@/shared/utils/formatters';
import { expect } from '@/shared/utils/matchers';

for (const tc of bookingCancelHappyTestCases) {
  test(tc.description, async ({ createCustomer, createUnitType, createUnit, createBooking, bookingDetailsPage }) => {
    const customer = await createCustomer(getCustomerCreateData());
    const unitType = await createUnitType(getUnitTypeCreateData());
    const unit = await createUnit(getUnitCreateData(unitType));
    const bookingData = getBookingCreateData({ customer, unitType, unit }, tc.initialOptions);
    const cancellation = getBookingCancelData(tc.cancellation);

    const { oldStatus, newStatus, moveOutDate } = toBookingCancellationDetails(bookingData, cancellation);

    const booking = await createBooking(bookingData);

    await bookingDetailsPage.goto(booking.id);

    const detailsPageAfterCancel = await test.step('cancel booking', async () => {
      const cancelDialog = await bookingDetailsPage.openBookingCancelDialog();
      return cancelDialog.cancel(cancellation);
    });

    await test.step('verify booking after cancel on details page', async () => {
      await expectSingleLocatorToHaveText(detailsPageAfterCancel.baseStatus, newStatus);

      if (oldStatus === 'scheduled') {
        await expect(detailsPageAfterCancel.canceledBeforeStartStatus).toBeVisible();
      } else if (oldStatus === 'active' && newStatus !== 'cancelled') {
        await expectSingleLocatorToHaveText(detailsPageAfterCancel.cancelsOnStatus, `ends on ${moveOutDate}`);
      }

      await expectSingleLocatorToHaveText(detailsPageAfterCancel.generalCard.moveOut, moveOutDate);
    });

    await test.step('verify booking after cancel on list page', async () => {
      const listPage = await detailsPageAfterCancel.returnToBookingListPage();

      await listPage.searchTextField.fill(formatId(booking.id));

      await expect(listPage.dataTable.getRows()).toHaveCount(1);
      await expectDataTableChipsColumnToHaveText(
        listPage.dataTable,
        bookingTableColumnTestIds.status,
        newStatus === 'cancelled' ? 'cancelled' : [newStatus, '']
      );
      await expectDataTableTextColumnToHaveText(listPage.dataTable, bookingTableColumnTestIds.moveOut, moveOutDate);
    });
  });
}
