import { BookingBasketContent } from '@/portal/modules/booking/components/BookingBasketContent';
import {
  BookingCreateDiscount,
  BookingCreateInsurance,
  BookingCreateUnitType,
} from '@/portal/modules/booking/booking-types';
import { CustomerType } from '@/shared/types/customer-types';
import { Location } from '@/shared/types/location-types';
import {
  formatAddressWithoutCountry,
  formatCurrency,
  formatDateLegacy,
  formatDiscount,
  formatPercentage,
} from '@/shared/utils/formatters';
import { decreaseByPercentage, increaseByPercentage } from '@/shared/utils/math-utils';
import { expect } from '@playwright/test';
import dayjs from 'dayjs';

export async function verifyBookingBasketContent(
  basketContent: BookingBasketContent,
  isMobile: boolean,
  customerType: CustomerType,
  moveInDate: Date,
  location: Location,
  unitType: BookingCreateUnitType,
  insurance?: BookingCreateInsurance,
  discount?: BookingCreateDiscount
): Promise<void> {
  const unitTypePriceExclVat = unitType.billing.price * unitType.billing.amount;
  const unitTypePriceDiscounted =
    discount &&
    (discount.type === 'fixed'
      ? unitTypePriceExclVat - discount.value
      : decreaseByPercentage(unitTypePriceExclVat, discount.value));
  const unitTypeTaxRate = customerType === 'private' ? unitType.taxes.b2c.rate : unitType.taxes.b2b.rate;
  const unitTypePriceInclVat = increaseByPercentage(unitTypePriceExclVat, unitTypeTaxRate);
  const unitTypePriceInclVatDiscounted =
    unitTypePriceDiscounted && increaseByPercentage(unitTypePriceDiscounted, unitTypeTaxRate);
  const insurancePriceExclVat = insurance && insurance.billing.price * insurance.billing.amount;
  const insuranceTaxRate =
    insurance && (customerType === 'private' ? insurance.taxes.b2c.rate : insurance.taxes.b2b.rate);
  const insurancePriceInclVat =
    insurancePriceExclVat && increaseByPercentage(insurancePriceExclVat, insuranceTaxRate ?? 0);
  const totalPrice = unitTypePriceInclVat + (insurancePriceInclVat ?? 0);
  const totalPriceDiscounted =
    unitTypePriceInclVatDiscounted && unitTypePriceInclVatDiscounted + (insurancePriceInclVat ?? 0);
  const recurringPaymentPrice = totalPrice;
  let recurringPaymentPriceDiscounted: number | undefined = undefined;

  if (discount) {
    if (discount.duration.option === 'multiple_months' && discount.duration.amount) {
      const billingEndDate = dayjs(moveInDate).add(
        unitType.billing.amount,
        unitType.billing.type === 'weekly' ? 'weeks' : 'months'
      );
      const discountEndDate = dayjs(moveInDate).add(discount.duration.amount, 'months');

      if (discountEndDate.isAfter(billingEndDate)) {
        recurringPaymentPriceDiscounted = totalPriceDiscounted;
      }
    } else if (discount.duration.option === 'forever') {
      recurringPaymentPriceDiscounted = totalPriceDiscounted;
    }
  }

  if (isMobile) {
    await expect(basketContent.location).toBeHidden();
  } else {
    await expect(basketContent.location).toBeVisible();
    await expect(basketContent.locationName).toHaveText(location.name);
    await expect(basketContent.locationAddress).toHaveText(
      formatAddressWithoutCountry(location.street, location.postalCode, location.city)
    );
  }

  await expect(basketContent.moveInDateValue).toHaveText(formatDateLegacy(moveInDate));
  await expect(basketContent.unitTypeName).toHaveText(unitType.name);
  await expect(basketContent.unitTypePriceInclVat).toHaveText(formatCurrency(unitTypePriceInclVat, location.currency));

  if (insurancePriceInclVat) {
    await expect(basketContent.insuranceName).toHaveText(insurance.name);
    await expect(basketContent.insurancePriceInclVat).toHaveText(
      formatCurrency(insurancePriceInclVat, location.currency)
    );
  } else {
    await expect(basketContent.insuranceName).toBeHidden();
    await expect(basketContent.insurancePriceInclVat).toBeHidden();
  }

  if (discount) {
    await expect(basketContent.discountCodeForm.discountTerms).toHaveText(
      formatDiscount(
        discount.duration,
        discount.type === 'percentage'
          ? formatPercentage(discount.value)
          : formatCurrency(discount.value, location.currency)
      )
    );
  } else {
    await expect(basketContent.discountCodeForm.discountTerms).toBeHidden();
  }

  if (totalPriceDiscounted) {
    await expect(basketContent.firstInvoiceOldPriceInclVat).toHaveText(formatCurrency(totalPrice, location.currency));
    await expect(basketContent.firstInvoiceNewPriceInclVat).toHaveText(
      formatCurrency(totalPriceDiscounted, location.currency)
    );
  } else {
    await expect(basketContent.firstInvoiceOldPriceInclVat).toBeHidden();
    await expect(basketContent.firstInvoiceNewPriceInclVat).toHaveText(formatCurrency(totalPrice, location.currency));
  }

  if (recurringPaymentPriceDiscounted) {
    await expect(basketContent.recurringPaymentOldPriceInclVat).toHaveText(
      formatCurrency(recurringPaymentPrice, location.currency)
    );
    await expect(basketContent.recurringPaymentNewPriceInclVat).toHaveText(
      formatCurrency(recurringPaymentPriceDiscounted, location.currency)
    );
  } else {
    await expect(basketContent.recurringPaymentOldPriceInclVat).toBeHidden();
    await expect(basketContent.recurringPaymentNewPriceInclVat).toHaveText(
      formatCurrency(recurringPaymentPrice, location.currency)
    );
  }
}
