Загрузка данных


import { OTHER_VALUES } from '@/domains/controller/components/CreateController/model/formNames';
import { normalizeSipUriForPayload } from '@/domains/equipment/repositories/helpers/normalizeSipUriForPayload';
import { toSecondaryInterfacePostDto } from '@/domains/equipment/repositories/helpers/toSecondaryInterfacePostDto';
import { toSecondaryInterfacePutDto } from '@/domains/equipment/repositories/helpers/toSecondaryInterfacePutDto';
import { useNetInterfaceRepository } from '@/domains/equipment/repositories/netInterface.repository';
import {
  DeviceModel,
  useGetApiV1SecondaryInterfaceValueOwnerByOwnerIdQuery,
  usePostApiV1SecondaryInterfaceValueMutation,
  usePutApiV1SecondaryInterfaceValueByIdMutation,
} from '@/shared/api/controller/client';
import { useCloseDrawer } from '@/shared/hooks/drawer/useCloseDrawer';
import { Helpers } from '@/shared/lib';
import { DrawerTypes } from '@/shared/model/drawer/drawer.types';
import {
  Ieee8021X,
  ProtocolIp,
  Segment,
} from '@/widgets/Monitoring/model/networkEquipment.model';
import { useEquipmentRepository } from '@/widgets/Monitoring/repositories/networkEquipment.repository';
import { yupResolver } from '@hookform/resolvers/yup';
import { QueryStatus } from '@reduxjs/toolkit/dist/query';
import { useSelectActiveNetworkEquipmentId } from '@shared/store/сontrollers/сontrollers.selectors';
import { enqueueSnackbar } from 'notistack';
import { useEffect, useState } from 'react';
import { SubmitHandler, UseFormReturn, useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import {
  NETWORK_EQUIPMENT_CREATE_FORM_KEY,
  NetworkEquipmentCreateFormData,
} from '../../NetworkEquipmentCreateDrawer/model/networkEquipmentCreateForm.model';
import { useGetNetworkEquipmentById } from '../../NetworkEquipmentInfoDrawer/hooks/useGetNetworkEquipmentById';
import { NetworkEquipmentUpdateFormData } from '../model/networkEquipmentUpdateForm.model';
import { networkEquipmentUpdateSchema } from '../validation/networkEquipmentUpdate.schema';

type NetworkEquipmentUpdateState = {
  networkEquipmentUpdateLabel: string;
  networkEquipmentUpdateDrawerLabel: string;
  methods: UseFormReturn<NetworkEquipmentUpdateFormData, any, undefined>;
  onDrawerClose: () => void;
  submitHandler: SubmitHandler<NetworkEquipmentUpdateFormData>;
  model: DeviceModel | undefined | null;
  isSaveButtonDisabled: boolean;
  handleClearModel: () => void;
  setModel: (value: DeviceModel | null) => void;
};

export const useNetworkEquipmentUpdateState =
  (): NetworkEquipmentUpdateState => {
    const { t } = useTranslation();

    const networkEquipmentId = useSelectActiveNetworkEquipmentId();

    const networkEquipmentUpdateLabel = t('common:buttons.save');
    const networkEquipmentUpdateDrawerLabel = t(
      'common:drawerTitle.NetworkEquipmentUpdate',
    );

    const closeDrawer = useCloseDrawer();
    const [model, setModel] = useState<DeviceModel | null>(null);

    const { updateNetworkEquipment, updateNetworkEquipmentQueryStatus } =
      useEquipmentRepository();

    const [updateSecondaryInterface] =
      usePutApiV1SecondaryInterfaceValueByIdMutation();

    const [saveSecondaryInterface] =
      usePostApiV1SecondaryInterfaceValueMutation();

    const networkEquipment = useGetNetworkEquipmentById();

    const id = networkEquipment?.id;

    const {
      data: secondaryInterfaceData,
      isSuccess: isSecondaryInterfaceSuccess,
    } = useGetApiV1SecondaryInterfaceValueOwnerByOwnerIdQuery(
      { ownerId: id! },
      { skip: !id },
    );

    const defaultValues: NetworkEquipmentUpdateFormData = {
      locationId: networkEquipment?.locationId ?? '',
      name: networkEquipment?.name ?? '',
      ip: networkEquipment?.interface?.ip ?? '',
      mac: networkEquipment?.interface?.mac ?? '',
      subnetMask: networkEquipment?.interface?.subnetMask ?? '',
      gateway: networkEquipment?.interface?.gateway ?? '',
      port: networkEquipment?.interface?.port ?? 8080,
      timeZone: networkEquipment?.timeZone ?? '',
      modelId: networkEquipment?.model?.id ?? '',
      typeName: networkEquipment?.model?.type?.name ?? '',
      sipUri: networkEquipment?.sipUri,
      hasSipUri: networkEquipment?.model?.type?.hasSipUri ?? null,
      manufacturerName: networkEquipment?.model?.manufacturer?.name ?? '',
      //@ts-ignore
      segment: networkEquipment?.segment ?? Segment.SIGMA,
      //@ts-ignore
      protocolIp: networkEquipment?.interface?.protocolIp ?? ProtocolIp.DHCP,
      ieee8021x: networkEquipment?.interface?.ieee8021x ?? Ieee8021X.MAB,
      description: networkEquipment?.description,
      telnetPort: networkEquipment?.telnetPort,
      firmware: networkEquipment?.firmware,
      serialNumber: networkEquipment?.serialNumber,
      inventoryNumber: networkEquipment?.inventoryNumber,
      sendNotifications: networkEquipment?.sendNotifications,
      controlPage: networkEquipment?.controlPage ?? '',
      netInterface: !!secondaryInterfaceData?.length,
      netInterfaceInfo:
        secondaryInterfaceData?.map((secondaryInterface) => {
          return {
            gateway: secondaryInterface.gateway,
            mac: secondaryInterface.mac,
            ip: secondaryInterface.ip,
            subnetMask: secondaryInterface.subnetMask,
            nameId: secondaryInterface.name?.id,
            id: secondaryInterface.id,
          };
        }) ?? [],
      disableMonitoring: networkEquipment?.disableMonitoring ?? false,
    };

    const methods = useForm({
      mode: 'onBlur',
      reValidateMode: 'onChange',
      resolver: yupResolver(networkEquipmentUpdateSchema),
      defaultValues,
    });

    const onDrawerClose = (): void => {
      methods.reset(defaultValues);
      setModel?.(null);
    };

    useEffect(() => {
      if (networkEquipment?.model) {
        setModel(networkEquipment.model);
      }
    }, [networkEquipment]);

    const handleClearModel = () => {
      methods.setValue('modelId', '');
      methods.setValue('manufacturerName', '');
      methods.setValue('typeName', '');
      methods.setValue('hasSipUri', null);
    };

    useEffect(() => {
      if (model) {
        methods.setValue('manufacturerName', model?.manufacturer?.name);
        methods.setValue('typeName', model?.type?.name);
        methods.setValue('hasSipUri', model.type?.hasSipUri);
      }
    }, [model]);

    useEffect(() => {
      methods.reset(defaultValues);
    }, [networkEquipment]);

    const submitHandler: SubmitHandler<NetworkEquipmentUpdateFormData> = (
      values,
    ) => {
      updateNetworkDevice(values as NetworkEquipmentCreateFormData);
    };

    const updateNetworkDevice = async (
      values: NetworkEquipmentCreateFormData,
    ) => {
      if (!id) {
        return;
      }

      const payload = normalizeSipUriForPayload(values);

      updateNetworkEquipment(payload as NetworkEquipmentCreateFormData, id);

      try {
        const secondaryInterfacePutDto = toSecondaryInterfacePutDto(
          values,
          networkEquipmentId || '',
          'network-device',
        );

        const newInterfaceList = values.netInterfaceInfo
          ?.filter((interfaceInfo) => !interfaceInfo.id)
          .map((newInterfaceInfo) => ({
            nameId: newInterfaceInfo.nameId as string,
            ip: newInterfaceInfo.ip,
            subnetMask: newInterfaceInfo.subnetMask,
            gateway: newInterfaceInfo.gateway,
            mac: newInterfaceInfo.mac,
          }));

        const secondaryInterfacePostDto = toSecondaryInterfacePostDto(
          newInterfaceList,
          id,
          'network-device',
        );

        if (secondaryInterfacePutDto?.length) {
          await Promise.all(
            secondaryInterfacePutDto
              .filter((dto) => dto.id)
              .map(async (dto) => {
                return await updateSecondaryInterface(dto) // тут не update, а create
                  .unwrap()
                  .catch((e) => {
                    enqueueSnackbar(e ?? '', { variant: 'error' });
                  });
              }),
          );
        }

        if (secondaryInterfacePostDto?.length) {
          await Promise.all(
            secondaryInterfacePostDto.map(async (dto) => {
              return await saveSecondaryInterface(dto)
                .unwrap()
                .catch((e) => {
                  enqueueSnackbar(e ?? '', { variant: 'error' });
                });
            }),
          );
        }
      } catch (e) {
        console.error(e);
      }
    };

    useEffect(() => {
      if (updateNetworkEquipmentQueryStatus === QueryStatus.fulfilled) {
        closeDrawer(DrawerTypes.networkEquipmentUpdate);
        methods.reset(defaultValues);
      }
    }, [updateNetworkEquipmentQueryStatus]);

    useEffect(() => {
      if (isSecondaryInterfaceSuccess && secondaryInterfaceData) {
        methods.setValue(
          OTHER_VALUES.netInterface,
          !!secondaryInterfaceData?.length,
        );
        methods.setValue(
          OTHER_VALUES.netInterfaceInfo,
          secondaryInterfaceData?.map((secondaryInterface) => {
            return {
              gateway: secondaryInterface.gateway,
              mac: secondaryInterface.mac,
              ip: secondaryInterface.ip,
              subnetMask: secondaryInterface.subnetMask,
              nameId: secondaryInterface.name?.id,
              id: secondaryInterface.id,
            };
          }),
        );
      }
    }, [isSecondaryInterfaceSuccess, secondaryInterfaceData]);

    const netInterfaceInfo = methods.watch(
      NETWORK_EQUIPMENT_CREATE_FORM_KEY.netInterfaceInfo,
    );
    const netInterface = methods.watch(
      NETWORK_EQUIPMENT_CREATE_FORM_KEY.netInterface,
    );

    const { deleteNetInterfaces } = useNetInterfaceRepository();

    useEffect(() => {
      (async () => {
        if (
          !netInterface &&
          isSecondaryInterfaceSuccess &&
          netInterfaceInfo &&
          !!netInterfaceInfo.length
        ) {
          await deleteNetInterfaces(
            netInterfaceInfo?.map((netInterface) => netInterface.id),
          );

          methods.setValue(
            NETWORK_EQUIPMENT_CREATE_FORM_KEY.netInterfaceInfo,
            [],
          );
        }
      })();
    }, [netInterface, netInterfaceInfo, isSecondaryInterfaceSuccess]);

    const { isValid, dirtyFields } = methods.formState;
    const isDirtyLocationId =
      methods.getValues().locationId !== defaultValues.locationId;
    const isDirtyFields = !Helpers.isEmpty(dirtyFields) || isDirtyLocationId;
    const isSaveButtonDisabled = !isDirtyFields || !isValid;

    return {
      networkEquipmentUpdateDrawerLabel,
      networkEquipmentUpdateLabel,
      methods,
      onDrawerClose,
      submitHandler,
      model,
      isSaveButtonDisabled,

      setModel,
      handleClearModel,
    };
  };