import {
  IUnit,
  IUnitEditGeneralData,
  IUnitEditMeasurementsData,
  IUnitMoveToStatus,
} from '@/manager/modules/unit/types/unit-types';
import {
  expectUnitDetailsPageAndThenListPageToShowCorrectData,
  expectUnitListPageAndThenDetailsPageToShowCorrectData,
} from '@/manager/modules/unit/utils/unit-entity-expect-utils';
import { UnitListPage } from '@/manager/modules/unit/views/UnitListPage';
import { expect } from '@/shared/utils/matcher-utils';

export async function expectUnitStatusToBeChanged(
  startPage: UnitListPage,
  oldUnit: IUnit,
  newStatus: IUnitMoveToStatus
): Promise<void> {
  const detailsPage = await expectUnitListPageAndThenDetailsPageToShowCorrectData(startPage, oldUnit);

  await detailsPage.moveTo(newStatus);

  const newUnit: IUnit = {
    ...oldUnit,
    status: newStatus,
  };

  await expectUnitDetailsPageAndThenListPageToShowCorrectData(detailsPage, newUnit);
}

export async function expectUnitStatusToNotBeChanged(
  startPage: UnitListPage,
  oldUnit: IUnit,
  newStatus: IUnitMoveToStatus
): Promise<void> {
  const detailsPage = await expectUnitListPageAndThenDetailsPageToShowCorrectData(startPage, oldUnit);

  await detailsPage.actionMenuButton.click();

  await expect(detailsPage.getActionMenuMoveToItem(newStatus)).toBeHidden();
}

export async function expectUnitMeasurementsToBeEdited(
  startPage: UnitListPage,
  oldUnit: IUnit,
  changes: IUnitEditMeasurementsData
): Promise<void> {
  const oldDetailsPage = await expectUnitListPageAndThenDetailsPageToShowCorrectData(startPage, oldUnit);

  const editDialog = await oldDetailsPage.openUnitEditMeasurementsDialog();
  const newDetailsPage = await editDialog.edit(changes);

  const newUnit: IUnit = {
    ...oldUnit,
    measurements: {
      area: changes.area === null ? undefined : (changes.area ?? oldUnit.measurements.area),
      ceilingHeight:
        changes.ceilingHeight === null ? undefined : (changes.ceilingHeight ?? oldUnit.measurements.ceilingHeight),
      width: changes.width === null ? undefined : (changes.width ?? oldUnit.measurements.width),
      depth: changes.depth === null ? undefined : (changes.depth ?? oldUnit.measurements.depth),
      volume: changes.volume === null ? undefined : (changes.volume ?? oldUnit.measurements.volume),
      doorType: changes.doorType === null ? undefined : (changes.doorType ?? oldUnit.measurements.doorType),
      doorWidth: changes.doorWidth === null ? undefined : (changes.doorWidth ?? oldUnit.measurements.doorWidth),
      doorHeight: changes.doorHeight === null ? undefined : (changes.doorHeight ?? oldUnit.measurements.doorHeight),
      floor: changes.floor === null ? undefined : (changes.floor ?? oldUnit.measurements.floor),
    },
  };

  await expectUnitDetailsPageAndThenListPageToShowCorrectData(newDetailsPage, newUnit);
}

export async function expectUnitGeneralInfoToBeEdited(
  startPage: UnitListPage,
  oldUnit: IUnit,
  changes: IUnitEditGeneralData
): Promise<void> {
  const oldDetailsPage = await expectUnitListPageAndThenDetailsPageToShowCorrectData(startPage, oldUnit);

  const editDialog = await oldDetailsPage.openUnitEditGeneralDialog();
  const newDetailsPage = await editDialog.edit(changes);

  const newUnit: IUnit = {
    ...oldUnit,
    name: changes.name ?? oldUnit.name,
    location: changes.location ?? oldUnit.location,
    unitType: changes.unitType ?? oldUnit.unitType,
    note: changes.note === null ? undefined : (changes.note ?? oldUnit.note),
    accessPermissions:
      changes.accessPermissions === null ? undefined : (changes.accessPermissions ?? oldUnit.accessPermissions),
  };

  await expectUnitDetailsPageAndThenListPageToShowCorrectData(newDetailsPage, newUnit);
}

export async function expectUnitGeneralInfoToNotBeEdited(
  startPage: UnitListPage,
  oldUnit: IUnit,
  changes: IUnitEditGeneralData
): Promise<void> {
  const detailsPage = await expectUnitListPageAndThenDetailsPageToShowCorrectData(startPage, oldUnit);

  const editDialog = await detailsPage.openUnitEditGeneralDialog();
  await editDialog.fill(changes);
  await editDialog.submitButton.click();

  await expect(editDialog.errors).toHaveCountGreaterThan(0);
}
