import { expectDataTableTextColumnToHaveText } from '@/manager/modules/ui/data-table/data-table-assertions';
import { unitTableColumnTestIds } from '@/manager/modules/ui/data-table/data/data-table-column-test-ids';
import { unitCreateHappyTestCases } from '@/manager/modules/unit/test-cases/unit-create-happy-test-cases';
import { verifyUnitMeasurementsCard } from '@/manager/modules/unit/unit-assertions';
import { getUnitCreateData } from '@/manager/modules/unit/unit-factories';
import { test } from '@/manager/modules/unit/unit-fixtures';
import { expectSingleLocatorToHaveText } from '@/manager/shared/utils/expect-utils';
import { getUnitTypeCreateData } from '@/manager/modules/unit-type/unit-type-factories';
import { formatSize, formatUnit } from '@/shared/utils/formatters';
import { expect } from '@/shared/utils/matchers';

for (const tc of unitCreateHappyTestCases) {
  test(tc.description, async ({ createUnitType, trackUnitForTeardown, unitCreateDialog }) => {
    const unitType = await createUnitType(getUnitTypeCreateData());
    const data = getUnitCreateData(unitType, tc.options);
    const unitTypeSizeColumn = formatSize(data.unitType.size, data.location.sizeFormat, 2);
    const area = formatUnit(data.measurements.area, 'm²');
    const width = formatUnit(data.measurements.width, 'cm');
    const depth = formatUnit(data.measurements.depth, 'cm');

    await unitCreateDialog.goto();

    const detailsPage = await test.step('create unit', () => unitCreateDialog.create(data));

    trackUnitForTeardown(detailsPage.getUnitId());

    await test.step('verify new unit on details page', async () => {
      await expectSingleLocatorToHaveText(detailsPage.title, data.name);
      await expectSingleLocatorToHaveText(detailsPage.status, data.status);
      await expectSingleLocatorToHaveText(detailsPage.generalCard.name, data.name);
      await expectSingleLocatorToHaveText(detailsPage.generalCard.location, data.location.name);
      await expectSingleLocatorToHaveText(detailsPage.generalCard.unitType, data.unitType.name);
      await expectSingleLocatorToHaveText(detailsPage.generalCard.note, data.note);
      await verifyUnitMeasurementsCard(detailsPage.measurementsCard, data.measurements);
      await expect(detailsPage.bookingsCard.dataTable.getRows()).toHaveCount(0);
    });

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

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

      await expect(listPage.dataTable.getRows()).toHaveCount(1);
      await expectDataTableTextColumnToHaveText(listPage.dataTable, unitTableColumnTestIds.name, data.name);
      await expectDataTableTextColumnToHaveText(
        listPage.dataTable,
        unitTableColumnTestIds.location,
        data.location.name
      );
      await expectDataTableTextColumnToHaveText(
        listPage.dataTable,
        unitTableColumnTestIds.unitType,
        data.unitType.name
      );
      await expectDataTableTextColumnToHaveText(listPage.dataTable, unitTableColumnTestIds.status, data.status);
      await expectDataTableTextColumnToHaveText(
        listPage.dataTable,
        unitTableColumnTestIds.unitTypeSize,
        unitTypeSizeColumn
      );
      await expectDataTableTextColumnToHaveText(listPage.dataTable, unitTableColumnTestIds.area, area);
      await expectDataTableTextColumnToHaveText(listPage.dataTable, unitTableColumnTestIds.width, width);
      await expectDataTableTextColumnToHaveText(listPage.dataTable, unitTableColumnTestIds.depth, depth);
      await expectDataTableTextColumnToHaveText(listPage.dataTable, unitTableColumnTestIds.customer, undefined);
    });
  });
}

test('rejects a unit without all required fields', async ({ createUnitType, unitCreateDialog }) => {
  const unitType = await createUnitType(getUnitTypeCreateData());
  const data = getUnitCreateData(unitType, { name: '' });

  await unitCreateDialog.goto();

  await test.step('submit invalid unit create form', async () => {
    await unitCreateDialog.fill(data);
    await unitCreateDialog.submit();
  });

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

test('rejects a unit with a duplicate name', async ({ createUnit, createUnitType, unitCreateDialog }) => {
  const unitType = await createUnitType(getUnitTypeCreateData());
  const existing = await createUnit(getUnitCreateData(unitType));
  const data = getUnitCreateData(unitType, { name: existing.name });

  await unitCreateDialog.goto();

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

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