import { getDepositCreateData } from '@/manager/modules/deposit/deposit-factories';
import { test } from '@/manager/modules/deposit/deposit-fixtures';
import { depositCreateHappyTestCases } from '@/manager/modules/deposit/test-cases/deposit-create-happy-test-cases';
import { expectDataTableTextColumnToHaveText } from '@/manager/modules/ui/data-table/data-table-assertions';
import { depositTableColumnTestIds } from '@/manager/modules/ui/data-table/data/data-table-column-test-ids';
import { expectSingleLocatorToHaveText } from '@/manager/shared/utils/expect-utils';
import { formatCurrency, formatPercentage } from '@/shared/utils/formatters';
import { expect } from '@/shared/utils/matchers';

for (const tc of depositCreateHappyTestCases) {
  test(tc.description, async ({ depositCreateDialog, trackDepositForTeardown }) => {
    const data = getDepositCreateData(tc.options);
    const formattedPrice = formatCurrency(data.priceExclVat, data.location.currency);

    await depositCreateDialog.goto();

    const detailsPage = await test.step('create deposit', () => depositCreateDialog.create(data));

    trackDepositForTeardown(detailsPage.getDepositId());

    await test.step('verify new deposit on details page', async () => {
      await expectSingleLocatorToHaveText(detailsPage.title, data.name);
      await expectSingleLocatorToHaveText(detailsPage.generalCard.name, data.name);
      await expectSingleLocatorToHaveText(detailsPage.generalCard.location, data.location.name);
      await expectSingleLocatorToHaveText(detailsPage.generalCard.priceExclVat, formattedPrice);
      await expectSingleLocatorToHaveText(detailsPage.taxCard.b2cTax, formatPercentage(data.taxes.b2c.rate));
      await expectSingleLocatorToHaveText(detailsPage.taxCard.b2bTax, formatPercentage(data.taxes.b2b.rate));
    });

    await test.step('verify new deposit on list page', async () => {
      const listPage = await detailsPage.returnToDepositListPage();

      await listPage.searchTextField.fill(data.name);

      await expect(listPage.dataTable.getRows()).toHaveCount(1);
      await expect(listPage.dataTable.getRowColumnByIndex(0, depositTableColumnTestIds.id)).not.toBeEmpty();
      await expectDataTableTextColumnToHaveText(listPage.dataTable, depositTableColumnTestIds.name, data.name);
      await expectDataTableTextColumnToHaveText(
        listPage.dataTable,
        depositTableColumnTestIds.location,
        data.location.name
      );
      await expectDataTableTextColumnToHaveText(
        listPage.dataTable,
        depositTableColumnTestIds.priceExclVat,
        formattedPrice
      );
    });
  });
}

test('rejects a deposit without all required fields', async ({ depositCreateDialog }) => {
  await depositCreateDialog.goto();

  await test.step('submit invalid deposit create form', () => depositCreateDialog.submit());

  await test.step('verify errors on form', async () => {
    await expect(depositCreateDialog.errors).toHaveCountGreaterThan(0);
  });
});

test('rejects a deposit with a duplicate name', async ({ createDeposit, depositCreateDialog }) => {
  const existing = await createDeposit(getDepositCreateData());
  const data = getDepositCreateData({ name: existing.name });

  await depositCreateDialog.goto();

  await test.step('submit deposit create form with duplicate name', async () => {
    await depositCreateDialog.fill(data);
    await depositCreateDialog.submit();
  });

  await test.step('verify errors on form', async () => {
    await expect(depositCreateDialog.errors).toHaveCountGreaterThan(0);
  });
});
