import { test } from '@/manager/modules/booking/booking-fixtures';
import { BookingPriceChange } from '@/manager/modules/booking/booking-types';
import { getFutureDate } from '@/shared/utils/date-utils';
import { formatId } from '@/shared/utils/formatters';
import { expect } from '@/shared/utils/matchers';

test.describe.configure({ mode: 'default', timeout: 120_000 });

// Removal is asynchronous: confirming queues the deletion, and background jobs revert the Stripe
// schedule before the row disappears — with no bounded completion window to wait on (locally the
// revert can exceed a minute or never land). Depending on queue speed the billing card shows either
// the transient queued chip or, if the jobs already ran, the empty price adjustment row ('-'), so
// the assertion accepts both removal states instead of polling for completion.
const removalStates = /Deletion in progress|^\s*-?\s*$/;

function getPriceChange(): BookingPriceChange {
  return {
    option: 'increase',
    value: 10,
    valueType: 'percentage',
    changeAt: getFutureDate(0, 'day'),
    adjustUnit: true,
    adjustRecurringProducts: false,
  };
}

test('removes a scheduled price change via the booking actions menu', async ({
  setupBookingCreateData,
  createBooking,
  createBookingPriceChange,
  bookingDetailsPage,
}) => {
  const booking = await createBooking(await setupBookingCreateData());
  await createBookingPriceChange([booking.id], getPriceChange());

  await bookingDetailsPage.goto(booking.id);

  await test.step('remove the price adjustment', async () => {
    const removeDialog = await bookingDetailsPage.openBookingRemovePriceChangeDialog();
    await removeDialog.confirm();
  });

  await test.step('verify the price adjustment removal', async () => {
    await expect(bookingDetailsPage.billingCard.priceAdjustment).toHaveText(removalStates, { useInnerText: true });
  });
});

test('removes a scheduled price change via the billing card', async ({
  setupBookingCreateData,
  createBooking,
  createBookingPriceChange,
  bookingDetailsPage,
}) => {
  const booking = await createBooking(await setupBookingCreateData());
  await createBookingPriceChange([booking.id], getPriceChange());

  await bookingDetailsPage.goto(booking.id);

  await test.step('remove the price adjustment', async () => {
    const removeDialog = await bookingDetailsPage.billingCard.priceChangeSection.openRemovePriceChangeDialog();
    await removeDialog.confirm();
  });

  await test.step('verify the price adjustment removal', async () => {
    await expect(bookingDetailsPage.billingCard.priceAdjustment).toHaveText(removalStates, { useInnerText: true });
  });
});

test('removes a scheduled price change via the booking list', async ({
  setupBookingCreateData,
  createBooking,
  createBookingPriceChange,
  bookingListPage,
  bookingDetailsPage,
}) => {
  const booking = await createBooking(await setupBookingCreateData());
  await createBookingPriceChange([booking.id], getPriceChange());

  await bookingListPage.goto();

  await test.step('select the booking in the list', async () => {
    await bookingListPage.searchTextField.fill(formatId(booking.id));
    await bookingListPage.selectBookings(0);
  });

  await test.step('remove the price adjustment', async () => {
    const removeDialog = await bookingListPage.openBookingRemovePriceChangeDialog();
    await removeDialog.confirm();
  });

  await test.step('verify the price adjustment removal', async () => {
    await bookingDetailsPage.goto(booking.id);
    await expect(bookingDetailsPage.billingCard.priceAdjustment).toHaveText(removalStates, { useInnerText: true });
  });
});
