// Hooks
import { FC, useEffect, useMemo, useState } from 'react';

// Antd
import { Button, Form } from 'antd';

// Function
import {
  currentPageForLoadingAfterDeleteAction,
  usePathName,
} from 'components/DashboardTable';
import { useGroupTableColumns } from 'components/DashboardTable/useGroupTableColumns';
import {
  openNotificationError,
  openNotificationSuccess,
  openNotificationWarning,
  useProgressNotification,
} from 'components/Messages';
import { useStore } from 'stores/StoreProvider';

// Types
import { RootStore } from 'stores/RootStore';
import { TypeTags } from 'types/default';
import {
  ArmaIndustrialFirewall,
  DeviceType,
  EndpointDevice,
  SensorDevice,
} from 'myApi';
import { ColumnsType } from 'antd/es/table';
import { AxiosResponse } from 'axios';
import { TypeActionButtonsConfig } from 'components/DashboardTable/components/useActionsWithSelectedCards/types';
import { TypeGroupsData } from 'components/DashboardTable/types';
import {
  TCommonMessages,
  useCommonMessages,
  useCommonValidationMessages,
} from 'components/i18n';
import { EndpointGroupName } from './types';
import { Notification } from 'components/types';

// Components
import Dashboard from 'components/Dashboard';
import useActionsWithSelectedCards from 'components/DashboardTable/components/useActionsWithSelectedCards';
import { CardInfoDrawer } from 'components/Modals/CardInfoDrawer/CardInfoDrawer';
import { GeneralForm } from './DevicesCardInfo/GeneralForm';
import { TagDrawer } from 'components/Modals/TagDrawer/TagDrawer';
import { useDevicesLeftSideBarContents } from './DevicesLeftSideBarContent';
import { useDevicesMessages } from './i18n';
import { makeDevicesColumns } from './makeDevicesColumns';
import {
  checkForExistingFields,
  collectionButtonForDeviceCollectiveActions,
} from './helpers';

// Apps
import { observer } from 'mobx-react-lite';
import moment from 'moment';
import styles from 'components/DashboardTable/DashboardTable.module.scss';

export const DevicesDashboard: FC = observer(() => {
  const rootStore: RootStore = useStore();
  const devicesUiStore = rootStore.devicesUiStore;
  const devicesStore = rootStore.devicesStore;
  const endpointUiStore = rootStore.endpointUiStore;
  const endpointStore = rootStore.endpointStore;
  const firewallStore = rootStore.firewallStore;
  const sensorStore = rootStore.sensorStore;

  const antivirusResultTableUiStore = rootStore.antivirusResultTableUiStore;

  const { postClamAVDB } = antivirusResultTableUiStore;

  const {
    getSelectedTagId,
    getSelectedTag,
    groupList,
    postGroupsList,
    patchGroupsList,
    setSelectedTag,
  } = devicesUiStore;

  const [form] = Form.useForm<
    ArmaIndustrialFirewall | EndpointDevice | SensorDevice
  >();

  const pathName = usePathName();

  const commonTranslation: TCommonMessages = useCommonMessages();

  const localeValidation = useCommonValidationMessages();

  const {
    notification,
    table: { columnMessages, button },
    localeCardInfo,
    singleActionMessages,
    collectiveActionsMessages,
  } = useDevicesMessages();

  const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);

  useEffect(() => {
    devicesUiStore.setTypeSelectedCard(null);
    devicesUiStore.setCardSize(undefined);
    setSelectedTag(null);
  }, [pathName, setSelectedTag, devicesUiStore.setTypeSelectedCard]);

  useEffect(() => {
    if (pathName === '/security_systems/group') {
      devicesUiStore.fetchGroups();
    } else {
      devicesUiStore.fetchEventSourceDevices();
      devicesUiStore.fetchGroups();
    }
  }, [
    pathName,
    devicesUiStore.getSorterField,
    devicesUiStore.fetchGroups,
    devicesUiStore.fetchEventSourceDevices,
    devicesUiStore.groupDashboardState.current,
    devicesUiStore.groupDashboardState.pageSize,
    devicesUiStore.eventSourceDashboardState.current,
    devicesUiStore.eventSourceDashboardState.pageSize,
  ]);

  const { activateProgressMessage, stopProgressMessage } =
    useProgressNotification({
      key: 'progress',
      title: commonTranslation.notification[Notification.ProgressTitle],
      makeDescription: (seconds) =>
        seconds
          ? commonTranslation.notification[Notification.ProgressSubTitle](
              seconds,
            )
          : '',
    });

  // Одиночные действия
  // -------------------------------------------------------------

  // Удаление устройства
  const onDeleteDevice = async (ids: number[]): Promise<void> => {
    await devicesUiStore.deleteDevice(ids);
    if (ids.length === 1) {
      setSelectedRowKeys((prevState) => {
        return prevState.filter((id) => id !== ids[0]);
      });
    }
    const newCurrentPage = currentPageForLoadingAfterDeleteAction(
      devicesUiStore.eventSourceDashboardState,
      devicesUiStore.devicesList.length,
      ids,
    );
    devicesUiStore.setEventSourceDashboardState(
      newCurrentPage,
      devicesUiStore.eventSourceTablePageSize,
    );
    await devicesUiStore.fetchEventSourceDevices();
  };

  // Редактирование устройства
  const onEditDevice = async (type: DeviceType, id: number): Promise<void> => {
    if (type === DeviceType.Endpoint) {
      await endpointStore.fetchEndpointDetailById(id);
      await devicesUiStore.endpointFillFormData(form);
    } else if (type === DeviceType.Firewall) {
      await firewallStore.fetchFirewallDetailById(id);
      devicesUiStore.firewallFillFormData(form);
    } else if (type === DeviceType.Sensor) {
      await sensorStore.fetchSensorDetailById(id);
      devicesUiStore.sensorFillFormData(form);
    }

    devicesUiStore.setIsDisabledForm(false);
    devicesUiStore.setTypeSelectedCard(type);
    devicesUiStore.setCardSize('small');
  };

  // Загрузка конфигурации в зависимости от типа устройства
  const onDownloadDeviceConfig = async (
    type: string,
    id: number,
  ): Promise<void> => {
    if (type === 'firewall') {
      try {
        await devicesUiStore.downloadConfigFirewall([id]);
        openNotificationSuccess({
          messageTitle: notification.saved,
          messageDescription: notification.successSavedConfiguration,
        });
      } catch (e) {
        openNotificationError({
          messageTitle: notification.failedSavedConfiguration,
          messageDescription: notification.tryLater,
        });
      }
    }
    if (type === 'endpoint') {
      try {
        await devicesUiStore.downloadConfigEndpoint(id);
        openNotificationSuccess({
          messageTitle: notification.saved,
          messageDescription: notification.successSavedConfiguration,
        });
      } catch (e) {
        openNotificationError({
          messageTitle: notification.failedSavedConfiguration,
          messageDescription: notification.tryLater,
        });
      }
    }
  };

  // Загрузка на бэк конфигурации устройства IF в зависимости от типа действия
  const onUploadConfiguration = async (
    type: 'config' | 'rules',
    id: number,
    files?: FormData,
  ): Promise<void> => {
    if (type === 'config') {
      try {
        await devicesUiStore.uploadConfigFirewall([id], files as FormData);
        openNotificationSuccess({
          messageTitle: notification.uploaded,
          messageDescription: notification.uploadedConfiguration,
        });
      } catch (e) {
        openNotificationError({
          messageTitle: 'Во время загрузки конфигурации IF произошла ошибка',
        });
      }
    }
    if (type === 'rules' && files) {
      openNotificationSuccess({
        messageTitle: notification.preUploadedRules,
      });
      const response = await devicesUiStore.uploadRulesFirewall([id], files);
      let data;

      response.forEach((res) => {
        if (res.status === 'fulfilled') {
          data = res.value;
          if (data.response.success > 0 && data.response.failed === 0)
            openNotificationSuccess({
              messageTitle: notification.uploaded,
              messageDescription: notification.uploadedRules,
            });
          if (data.response.failed > 0 && data.response.success > 0)
            openNotificationWarning({
              messageTitle: notification.uploaded,
              messageDescription: notification.uploadedRulesNotFullRules(
                data.response.success,
                data.response.success + data.response.failed,
              ),
            });
          if (data.response.failed && !data.response.success)
            openNotificationError({
              messageTitle: notification.uploadedError,
              messageDescription: notification.uploadedErrorDescription,
            });
        }
      });
    }
  };

  // Обновление конфигурации с Endpoint
  const onUpdateConfiguration = async (ids: number[]): Promise<void> => {
    try {
      const response = await devicesUiStore.updateEndpoint(ids);
      const failedRequests = response.filter(
        (item) => item.status === 'rejected',
      );
      if (!failedRequests.length) {
        openNotificationSuccess({
          messageTitle: notification.updated,
          messageDescription: notification.updatedConfiguration,
        });
      } else {
        openNotificationError({
          messageTitle: notification.updatedError,
          messageDescription: notification.updatedErrorDescription,
        });
      }
    } catch (e) {
      openNotificationError({
        messageTitle: notification.updatedError,
        messageDescription: notification.updatedErrorDescription,
      });
    }
  };

  // Копирование Endpoint
  const onCopyEndpointConfiguration = async (id: number): Promise<void> => {
    devicesUiStore.setIsCopyEndpointStatus(true);
    devicesUiStore.setTypeSelectedCard(DeviceType.Endpoint);
    try {
      await endpointStore.fetchEndpointDetailById(id);
      await devicesUiStore.endpointFillFormData(form);
      devicesUiStore.setCardSize('small');
      devicesUiStore.setIsDisabledForm(false);
    } catch {
      devicesUiStore.setIsCopyEndpointStatus(false);
    }
  };

  const onRebootFirewall = async (id: number): Promise<void> => {
    activateProgressMessage();
    try {
      await devicesStore.rebootFirewall(id);
      openNotificationSuccess({
        messageTitle: notification.firewallReboot.success,
      });
      stopProgressMessage();
    } catch (e) {
      openNotificationError({
        messageTitle: notification.firewallReboot.failed,
        messageDescription: notification.tryAgain,
      });
      stopProgressMessage();
    }
  };

  // Групповые действия с устройствами
  //-----------------------------------------------------------

  const completeOrErrorNotification = (
    response: PromiseSettledResult<unknown>[],
  ): void => {
    let resolved = '';
    let rejected = '';
    setSelectedRowKeys((prevState) => {
      const currentIds: number[] = [];
      prevState.forEach((item) => {
        response.forEach((elem) => {
          if ('reason' in elem && elem.reason === item) {
            currentIds.push(item);
            rejected = 'rejected';
          } else if ('value' in elem) {
            resolved = 'resolved';
          }
        });
      });
      return currentIds;
    });
    if (resolved && rejected) {
      openNotificationWarning({
        messageTitle: collectiveActionsMessages.warningMessage,
        messageDescription:
          collectiveActionsMessages.descriptionErrorAndWarningMessage,
      });
    } else if (rejected) {
      openNotificationError({
        messageTitle: collectiveActionsMessages.errorMessage,
        messageDescription:
          collectiveActionsMessages.descriptionErrorAndWarningMessage,
      });
    } else if (resolved) {
      openNotificationSuccess({
        messageTitle: collectiveActionsMessages.successMessages,
      });
    }
  };

  // Экспорт CSV
  const onExport = async (): Promise<void> => {
    await devicesUiStore.exportCSV();
  };

  const onUpdateClamAVDB = async (file: FormData): Promise<void> => {
    try {
      await postClamAVDB(file);
      openNotificationSuccess({
        messageTitle: notification.updatedClamAVDBSuccess,
      });
    } catch (e) {
      openNotificationWarning({
        messageTitle: notification.updatedClamAVDBWarningFileExistTitle,
        messageDescription:
          notification.updatedClamAVDBWarningFileExistSubTitle,
      });
    }
  };

  // Удаление выбранных устройств
  const onCollectiveDeviceDelete = async (): Promise<void> => {
    await onDeleteDevice(selectedRowKeys);
    setSelectedRowKeys([]);
  };

  // Обновление конфигурации Firewall
  const onCollectiveUploadFirewallConfiguration = async (
    file: FormData,
  ): Promise<void> => {
    const response = await devicesUiStore.uploadConfigFirewall(
      selectedRowKeys,
      file as FormData,
    );
    completeOrErrorNotification(response);
  };

  // Обновление правил СОВ Firewall
  const onCollectiveFirewallIDSRulesUpdated = async (
    file: FormData,
  ): Promise<void> => {
    // Тут производим сортировку online и других статусов фаерволов. На тех фаерволах что отличны от онлайн,
    // мы не будем запускать обновление правил. Так как они выключены и бэк каждый отключеный обрабатывает секунд 20.
    // Это долго. Мы их сразу не будем включать в запрос, а пользователю об этом скажем в уведомлении и оставим чекбоксы на них отмечеными.
    const onlineFirewall: number[] = [];
    const offlineFirewall: number[] = [];

    // Тут разделяем online и offline статусы
    Object.entries(devicesUiStore.getFirewallOnlineStatus).forEach(
      ([firewallId, firewallStatus]) => {
        if (firewallStatus !== 'online') {
          offlineFirewall.push(parseInt(firewallId));
        } else {
          onlineFirewall.push(parseInt(firewallId));
        }
      },
    );

    // Показываем уведомление о том что обновление базы СОВ запущено
    openNotificationSuccess({
      messageTitle: notification.preUploadedRules,
    });

    // Тут мы сравниваем и отдеояем online фаерволы на старнице с выбранными для передачи их в запрос
    const currentSelectedOnlineFirewall = onlineFirewall.filter((elem) =>
      !selectedRowKeys.includes(elem) ? null : elem,
    );

    // Запускаем запрос на обновление с уже отфильтрованными фаерволами - только со статусом online
    const response = await devicesUiStore.uploadRulesFirewall(
      currentSelectedOnlineFirewall,
      file as FormData,
    );

    // Перебираем ответ и выясняем, если ли в ответе какие то фаерволы
    // с проваленными файлами обновления из переданного ему массива.
    // Если таковые имеются то пушим их в offlineFirewall, что бы потом оставить на них галочку в таблице, так как это действие не успешно,
    // хоть и частично
    response.forEach((item) => {
      if (item.status === 'fulfilled') {
        if (item.value.response.failed > 0) {
          offlineFirewall.push(item.value.id);
        }
      }
      if (item.status === 'rejected') {
        offlineFirewall.push(item.reason.id);
      }
    });

    // Тут мы сравниваем и отделяем offline фаерволы на старнице с выбранными
    const currentSelectedOfflineFirewall = offlineFirewall.filter((elem) =>
      !selectedRowKeys.includes(elem) ? null : elem,
    );

    // Уведомления --------- Начало ---------------
    // Эта чать показывает Warning notification. Частично что-то выполнилось, что-то нет
    // в том числе в массив currentSelectedOfflineFirewall попали id фаерволов которые не ушли в запрос
    if (
      currentSelectedOfflineFirewall.length &&
      currentSelectedOnlineFirewall.length
    ) {
      openNotificationWarning({
        messageTitle:
          collectiveActionsMessages.uploadFireWallRules.notification.warning,
        messageDescription: notification.tryAgain,
      });

      setSelectedRowKeys(currentSelectedOfflineFirewall);

      // Эта чать показывает Error notification. Вообще ничего не выполнилось,
      // в том числе в массив currentSelectedOfflineFirewall попали id фаерволов которые не ушли в запрос
    } else if (
      currentSelectedOfflineFirewall.length &&
      !currentSelectedOnlineFirewall.length
    ) {
      openNotificationError({
        messageTitle: collectiveActionsMessages.errorMessage,
        messageDescription: notification.tryAgain,
      });

      setSelectedRowKeys(currentSelectedOfflineFirewall);

      // Эта чать показывает Success notification. Все запросы выполнились успешно
    } else if (
      currentSelectedOnlineFirewall.length &&
      !currentSelectedOfflineFirewall.length
    ) {
      openNotificationSuccess({
        messageTitle:
          collectiveActionsMessages.uploadFireWallRules.notification.success,
      });
      setSelectedRowKeys([]);
    }
  };
  // Уведомления --------- Конец ---------------

  // Обновление конфигурации с Endpoint
  const onCollectiveUpdateEndpointConfiguration = async (): Promise<void> => {
    const response = await devicesUiStore.updateEndpoint(selectedRowKeys);
    completeOrErrorNotification(response);
  };

  const deviceTableColumns: ColumnsType<
    ArmaIndustrialFirewall | EndpointDevice | SensorDevice
  > = makeDevicesColumns(
    {
      columnMessages,
      singleActionMessages,
      commonMessages: commonTranslation.confirmText,
    },
    {
      onDelete: onDeleteDevice,
      onEdit: onEditDevice,
      onDownload: onDownloadDeviceConfig,
      onUpload: onUploadConfiguration,
      onUpdate: onUpdateConfiguration,
      onCopyEndpoint: onCopyEndpointConfiguration,
      onRebootFirewall: onRebootFirewall,
    },
  );

  // Удаление группы
  const onDeleteGroup = async (id: number[]): Promise<void> => {
    try {
      await devicesUiStore.deleteGroupsRecord(id);
      currentPageForLoadingAfterDeleteAction(
        devicesUiStore.groupDashboardState,
        groupList.length,
        id,
      );
      await devicesUiStore.fetchGroups();
      openNotificationSuccess({
        messageTitle: notification.groupSuccessDelete,
      });
    } catch {
      openNotificationError({
        messageTitle: notification.groupFailedDelete,
      });
    }
  };

  // Редактирование группы
  const onEditGroup = (id: number): void => {
    devicesUiStore.setSelectedTag(id);
    devicesUiStore.setCardSize('small');
    devicesUiStore.setIsDisabledForm(false);
  };

  // Создание колонок группы
  const groupTableColumns: ColumnsType<TypeGroupsData> = useGroupTableColumns({
    onDelete: onDeleteGroup,
    onEdit: onEditGroup,
  });

  // Возвращение колонок, карточек и пагинации в зависимости от url
  const { cards, columns, pageState } = useMemo(() => {
    const isDevicePage = pathName === '/security_systems';
    return {
      cards: isDevicePage ? devicesUiStore.devicesList : groupList,
      columns: isDevicePage ? deviceTableColumns : groupTableColumns,
      pageState: isDevicePage
        ? devicesUiStore.eventSourceDashboardState
        : devicesUiStore.groupDashboardState,
    };
  }, [
    devicesUiStore.eventSourceDashboardState,
    deviceTableColumns,
    devicesUiStore.devicesList,
    devicesUiStore.groupDashboardState,
    groupList,
    groupTableColumns,
    pathName,
  ]);

  const onSearch = (value: string): string => value;

  // Событие по нажатию на карточке в таблице
  const onRowEvent = async (
    card: ArmaIndustrialFirewall | EndpointDevice | SensorDevice,
  ): Promise<void> => {
    if (pathName === '/security_systems') {
      if (card.id) {
        devicesUiStore.setLoadingCard(true);
        if (card.type === DeviceType.Endpoint) {
          try {
            await endpointStore.fetchEndpointDetailById(card.id);
            await devicesUiStore.endpointFillFormData(form);
            devicesUiStore.setTypeSelectedCard(DeviceType.Endpoint);
          } catch (e) {
            openNotificationError({
              messageTitle: notification.failedFetchEventSourceData,
              messageDescription: notification.tryLater,
            });
          }
        }
        if (card.type === DeviceType.Firewall) {
          try {
            await firewallStore.fetchFirewallDetailById(card.id);
            devicesUiStore.firewallFillFormData(form);
            devicesUiStore.setTypeSelectedCard(DeviceType.Firewall);
          } catch (e) {
            openNotificationError({
              messageTitle: notification.failedFetchEventSourceData,
              messageDescription: notification.tryLater,
            });
          }
        }
        if (card.type === DeviceType.Sensor) {
          try {
            await devicesUiStore.sensorActionsByOnRowEvent(card.id, form);
          } catch (e) {
            openNotificationError({
              messageTitle: notification.failedFetchEventSourceData,
              messageDescription: notification.tryLater,
            });
          }
        }
        // Устанавливаем маленькую карточку
        devicesUiStore.setCardSize('small');
        // Дизэйблим форму
        devicesUiStore.setIsDisabledForm(true);
        // Loading - false
        devicesUiStore.setLoadingCard(false);
      }
    }
  };

  // Изменение пагинации
  const changeRowCount = (current: number, pageSize: number): void => {
    if (pathName === '/security_systems') {
      devicesUiStore.setEventSourceDashboardState(current, pageSize);
    } else {
      devicesUiStore.setGroupDashboardState(current, pageSize);
    }
  };

  // Кнопка на странице: Добавление устройства / Добавление группы
  const addNewEntity = {
    entity:
      pathName === '/security_systems' ? (
        <Button
          type="primary"
          className={styles['download_button']}
          onClick={() => {
            devicesUiStore.setCardSize('small');
            devicesUiStore.resetRotationType();
            devicesUiStore.setIsDisabledForm(false);
            devicesUiStore.setTypeSelectedCard(null);
            endpointStore.clearEndpointDetailById();
            firewallStore.clearFirewallDetailById();
            sensorStore.clearSensorDetailById();
            form.setFieldValue('group', undefined);
          }}
        >
          {button.addDevice}
        </Button>
      ) : (
        <Button
          type="primary"
          className={styles['download_button']}
          onClick={() => {
            devicesUiStore.setSelectedTag(undefined);
            devicesUiStore.setIsDisabledForm(false);
          }}
        >
          {button.addGroup}
        </Button>
      ),
  };

  // Закрытие карточки
  const onCloseCard = (): void => {
    devicesUiStore.resetCard();
    form.resetFields();
  };

  // Действия после успешного запроса
  const successRequest = async (messageTitle: string): Promise<void> => {
    openNotificationSuccess({
      messageTitle,
    });
    devicesUiStore.setCardSize(undefined);
    devicesUiStore.setTypeSelectedCard(null);
    devicesUiStore.setIsDisabledForm(true);
    form.resetFields();
    if (
      devicesUiStore.eventSourceDashboardState.pageSize ===
      devicesUiStore.devicesList.length
    ) {
      const newCurrentPage =
        devicesUiStore.eventSourceDashboardState.current + 1;
      devicesUiStore.setEventSourceDashboardState(
        newCurrentPage,
        devicesUiStore.eventSourceTablePageSize,
      );
      await devicesUiStore.fetchEventSourceDevices();
    }
    await devicesUiStore.fetchEventSourceDevices();
  };

  const validateExistFiles = (e: AxiosResponse): void => {
    const err = e as AxiosResponse;
    const existFields = Object.keys(err.data);
    form.setFields(
      checkForExistingFields(
        localeCardInfo.formFieldValidation.fieldExist,
        {
          ip: localeCardInfo.endpoint[EndpointGroupName.Main].ip,
          port: localeCardInfo.endpoint[EndpointGroupName.Main].port,
        },
        existFields,
      ),
    );
  };

  // Отправка формы карточки
  const onFinish = async (
    values: ArmaIndustrialFirewall | EndpointDevice | SensorDevice,
  ): Promise<void> => {
    if (devicesUiStore.typeSelectedDevice === DeviceType.Endpoint) {
      // Подготовка данных Endpoint для бэка
      const endpointValues: EndpointDevice = values;
      const prepareEndpointValues = {
        ...endpointValues,
        antivirus_paths: endpointUiStore.getAntivirusTablePath.map(
          (item) => item.path,
        ),
        scan_paths: endpointUiStore.getIntegrityControlTablePath.map(
          (item) => item.path,
        ),
        white_list_paths: endpointUiStore.getWhiteListTablePathTablePath.map(
          (item) => item.path,
        ),
        event_rotation_time: moment(endpointValues?.event_rotation_time).format(
          'HH:mm:ss',
        ),
        group: endpointValues.group ? endpointValues.group : null,
      };

      // Post - Подключение нового или копируемого Endpoint
      if (!form.getFieldValue('id')) {
        try {
          await devicesUiStore.postEndpointDevice(prepareEndpointValues);
          await successRequest(notification.newDevicesConnected);
          devicesUiStore.setIsCopyEndpointStatus(false);
        } catch (e) {
          if (e) {
            const err = e as AxiosResponse;
            validateExistFiles(err);
          }
        }
      } else {
        // Patch - Изменение Endpoint
        try {
          await devicesUiStore.patchEndpointDevice(
            prepareEndpointValues,
            form.getFieldValue('id'),
          );
          openNotificationSuccess({
            messageTitle: notification.deviceChanged,
          });
          devicesUiStore.setCardSize(undefined);
          devicesUiStore.setIsDisabledForm(true);
          form.resetFields();
        } catch (e) {
          if (e) {
            const err = e as AxiosResponse;
            if (err.data.port || err.data.ip) {
              validateExistFiles(err);
            } else {
              openNotificationError({
                messageTitle: notification.endpointFailChangeConfiguration,
              });
            }
          }
        }
      }
    } else if (devicesUiStore.typeSelectedDevice === DeviceType.Firewall) {
      // Подготовка данных Firewall для бэка
      const firewallValues: ArmaIndustrialFirewall = values;
      const prepareFirewallValues = {
        ...firewallValues,
        group: firewallValues.group ? firewallValues.group : null,
      };

      // Post - Подключение Firewall
      if (!form.getFieldValue('id')) {
        try {
          await devicesUiStore.postFirewallDevice(prepareFirewallValues);
          await successRequest(notification.newDevicesConnected);
          devicesUiStore.setCardSize(undefined);
        } catch (e) {
          if (e) {
            const err = e as AxiosResponse;
            if (err.data.port || err.data.ip) {
              validateExistFiles(err);
            } else {
              openNotificationError({
                messageTitle: notification.firewallFailConnect,
                messageDescription: notification.tryLater,
              });
            }
          }
        }
      } else {
        // Patch - Изменение Firewall
        try {
          await devicesUiStore.patchFirewallDevice(
            prepareFirewallValues,
            form.getFieldValue('id'),
          );
          openNotificationSuccess({
            messageTitle: notification.deviceChanged,
          });
          devicesUiStore.setCardSize(undefined);
          devicesUiStore.setIsDisabledForm(true);
          form.resetFields();
        } catch (e) {
          if (e) {
            const err = e as AxiosResponse;
            if (err.data.port || err.data.ip) {
              validateExistFiles(err);
            } else {
              openNotificationError({
                messageTitle: notification.firewallFailChangeConfiguration,
                messageDescription: notification.tryLater,
              });
            }
          }
        }
      }
    } else if (devicesUiStore.typeSelectedDevice === DeviceType.Sensor) {
      // Подготовка данных Sensor для бэка
      const sensorData: SensorDevice = values;
      delete sensorData.authorization_key;

      const prepareFireValues = {
        ...sensorData,
        group: sensorData.group ? sensorData.group : null,
      };

      // Создание Сенсора
      if (!form.getFieldValue('id')) {
        try {
          // Создаем ( подключаем ) новый сенсор.
          await devicesStore.createSensorDevice(prepareFireValues);

          // Записываем в форму данные из ответа, а именно - ключ авторизации, для заполнения поля "Ключ Авторизации,
          // и id ( для того что бы скрыть селект выбора устройств ),
          // Карточку тут закрывать не надо. Нужно копировать ключ и подключится к Сенсору.
          form.setFieldValue(
            'authorization_key',
            devicesStore.getSensorInformation?.authorization_key,
          );
          form.setFieldValue('id', devicesStore.getSensorInformation?.id);
          // Дизейблим форму, что бы случайно данные не поменять
          devicesUiStore.setIsDisabledForm(true);
        } catch (e) {
          if (e) {
            const err = e as AxiosResponse;
            if (err.data.port || err.data.ip) {
              validateExistFiles(err);
            } else {
              openNotificationError({
                messageTitle: notification.sensorFailedCreate,
                messageDescription: notification.tryLater,
              });
            }
          }
        }
      } else {
        // Изменение Сенсора
        try {
          await devicesStore.editSensorDevice(
            prepareFireValues,
            form.getFieldValue('id'),
          );
          openNotificationSuccess({
            messageTitle: notification.deviceChanged,
          });

          devicesUiStore.setCardSize(undefined);
          devicesUiStore.setIsDisabledForm(true);
          form.resetFields();
        } catch (e) {
          const err = e as AxiosResponse;
          if (err.data.port || err.data.ip) {
            validateExistFiles(err);
          } else {
            openNotificationError({
              messageTitle: notification.sensorFailChangeConfiguration,
              messageDescription: notification.tryLater,
            });
          }
        }
      }
    }
  };

  const handlePostGroup = async (values: TypeTags): Promise<void> => {
    try {
      await postGroupsList(values);
      openNotificationSuccess({
        messageTitle:
          commonTranslation.groupsMessages.notification.success.post,
      });
      if (devicesUiStore.groupDashboardState.pageSize === groupList.length) {
        const newCurrentPage = devicesUiStore.groupDashboardState.current + 1;
        devicesUiStore.setGroupDashboardState(
          newCurrentPage,
          devicesUiStore.eventSourceTablePageSize,
        );
      }
    } catch (e) {
      openNotificationError({
        messageTitle:
          commonTranslation.groupsMessages.notification.error.duplicateName,
      });
    }
  };

  const handlePatchGroup = async (
    values: TypeTags,
    selectedTag: number,
  ): Promise<void> => {
    try {
      await patchGroupsList(values, selectedTag);
      openNotificationSuccess({
        messageTitle:
          commonTranslation.groupsMessages.notification.success.patch,
      });
    } catch (e) {
      openNotificationError({
        messageTitle:
          commonTranslation.groupsMessages.notification.error.duplicateName,
      });
    }
  };

  const hasSelected = selectedRowKeys.length > 0;

  // Отображение корректных кнопок для коллективных действий
  const currentAction = useMemo((): TypeActionButtonsConfig[] => {
    const action = collectionButtonForDeviceCollectiveActions(
      collectiveActionsMessages,
      {
        onExport,
        onUpdateClamAVDB,
        onCollectiveDeviceDelete,
        onCollectiveUploadFirewallConfiguration,
        onCollectiveFirewallIDSRulesUpdated,
        onCollectiveUpdateEndpointConfiguration,
      },
      hasSelected,
    );

    const actions: TypeActionButtonsConfig[] = [
      action.exports,
      action.updateClamAVDB,
      action.delete,
    ];

    const deviceTypes = Object.entries(devicesUiStore.devicesTypes)
      .filter(([deviceId]) => selectedRowKeys.includes(parseInt(deviceId)))
      .map(([, deviceType]) => deviceType);

    if (
      !deviceTypes.includes(DeviceType.Firewall) &&
      deviceTypes.includes(DeviceType.Endpoint)
    ) {
      actions.push(action.updateEndpointConfig);
    } else if (
      deviceTypes.includes(DeviceType.Firewall) &&
      !deviceTypes.includes(DeviceType.Endpoint)
    ) {
      actions.push(action.uploadFireWallConfig, action.uploadIDSRules);
    }

    return actions;
  }, [
    collectiveActionsMessages,
    devicesUiStore.devicesTypes,
    hasSelected,
    selectedRowKeys,
  ]);

  // Объект таблицы для работы с выбранными элементами и их отображением
  const rowSelection: {
    selectedRowKeys: number[];
    onSetSelectedRowItem: (ids: number[]) => void;
  } = {
    selectedRowKeys,
    onSetSelectedRowItem: setSelectedRowKeys,
  };

  return (
    <Dashboard
      columns={columns}
      cards={cards}
      loading={devicesUiStore.loading}
      onSearch={onSearch}
      onRowEvent={onRowEvent}
      setCheckedColumns={devicesUiStore.setCheckedColumns}
      getCheckedColumns={devicesUiStore.getCheckedColumns}
      setSorterField={devicesUiStore.setSorterField}
      pageState={pageState}
      actionsWithCards={useActionsWithSelectedCards(
        pathName === '/security_systems' ? currentAction : null,
      )}
      rowSelection={pathName === '/security_systems' ? rowSelection : null}
      filters={null}
      changeRowCount={changeRowCount}
      leftSideBarContent={useDevicesLeftSideBarContents()}
      addNewEntity={addNewEntity}
      tagDrawer={
        <TagDrawer
          translations={commonTranslation}
          title={
            getSelectedTag?.name || commonTranslation.groupsMessages.main.title
          }
          getSelectedTagId={getSelectedTagId}
          getSelectedTag={getSelectedTag}
          setSelectedTag={setSelectedTag}
          postGroupsList={handlePostGroup}
          patchGroupsList={handlePatchGroup}
          disabled={devicesUiStore.isDisabledForm}
          setDisabled={devicesUiStore.setIsDisabledForm}
        />
      }
      cardInfoComponent={
        <CardInfoDrawer
          formProps={form}
          title={devicesUiStore.cardInfoTitle(
            {
              newDevice: localeCardInfo.title,
              copyEndpoint: localeCardInfo.copyEndpointTitle,
            },
            form,
          )}
          loading={devicesUiStore.getLoadingCard}
          cardSize={devicesUiStore.cardSize}
          disabled={devicesUiStore.isDisabledForm}
          setDisabled={devicesUiStore.setIsDisabledForm}
          onToggleCardSize={devicesUiStore.toggleFormSize}
          onCloseCard={onCloseCard}
        >
          <GeneralForm
            form={form}
            onFinish={onFinish}
            locale={localeCardInfo}
            localeValidation={localeValidation}
          />
        </CardInfoDrawer>
      }
    />
  );
});
