import { makeAutoObservable, observable, toJS } from 'mobx';
import { RootStore } from 'stores/RootStore';
import {
  TUseColumns,
  TypeCardSize,
  TypeTagCreate,
  TypeTags,
} from 'types/default';
import { TypeRotationFormField, TypeUploadedIdsRules } from '../types';
import { TypeDashboardPaginationState } from 'components/Dashboard/types';
import {
  ArmaIndustrialFirewall,
  DeviceType,
  EndpointDevice,
  FirewallStatus,
  SensorDevice,
} from 'myApi';
import { FormInstance } from 'antd/lib/form';
import moment from 'moment/moment';

export class DevicesUiStore {
  constructor(private readonly rootStore: RootStore) {
    makeAutoObservable(this);
  }

  @observable checkedColumns: TUseColumns[] = [];

  @observable selectedTag: TypeTagCreate | TypeTags | undefined;

  @observable selectedTagId: number | undefined | null;

  // Текущая страница таблицы источников событий
  eventSourceTablePageCurrent = 1;

  // Число элементов на странице таблицы источников событий
  eventSourceTablePageSize = 10;

  // Текущая страница таблицы групп
  groupTablePageCurrent = 1;

  // Число элементов на странице таблицы групп
  groupTablePageSize = 10;

  // Поле сортировки для таблицы источников событий и групп
  sorterField = '';

  // Тип устройства с его ID
  devicesTypes: { [key: number]: DeviceType } = {};

  // Размер карточки
  cardSize: TypeCardSize = undefined;

  // Тип выбранного устройства
  typeSelectedDevice: DeviceType | null = null;

  // Статус копирования Endpoint
  isCopyEndpointStatus = false;

  // Имя копироуемого Endpoint
  nameOfCopiedEndpoint: string | undefined = undefined;

  // Заблокирована ли форма
  isDisabledForm = true;

  // Фаервол с его статусом
  firewallStatus: { [key: number]: FirewallStatus } = {};

  loadingCard = false;

  // Получение поля сортировки при его изменении
  get getSorterField(): string {
    return this.sorterField;
  }

  get getLoadingCard(): boolean {
    return this.loadingCard;
  }

  setLoadingCard = (value: boolean): void => {
    this.loadingCard = value;
  };

  // Изменение поля сортировки
  setSorterField = (value: string): void => {
    this.sorterField = value;
  };

  // Установить блокировку формы
  setIsDisabledForm = (newState: boolean): void => {
    this.isDisabledForm = newState;
  };

  // Смена пагинации таблицы источников событий
  setEventSourceDashboardState = (current: number, pageSize: number): void => {
    this.eventSourceTablePageCurrent = current;
    this.eventSourceTablePageSize = pageSize;
  };

  // Смена пагинации таблицы групп
  setGroupDashboardState = (current: number, pageSize: number): void => {
    this.groupTablePageCurrent = current;
    this.groupTablePageSize = pageSize;
  };

  // Задать размер карточки
  setCardSize = (newCardSize: TypeCardSize): void => {
    this.cardSize = newCardSize;
  };

  // Сброс настроек карточки
  resetCard = (): void => {
    this.setCardSize(undefined);
    this.setIsCopyEndpointStatus(false);
    this.setTypeSelectedCard(null);
    this.rootStore.endpointUiStore.clearTablePath();
  };

  toggleFormSize = (): void => {
    this.cardSize = this.cardSize === 'small' ? 'large' : 'small';
  };

  // Устанавливается флаг, копируется Endpoint или нет
  setIsCopyEndpointStatus = (value: boolean): void => {
    this.isCopyEndpointStatus = value;
  };

  // Получение пагинации для таблицы источников событий
  get eventSourceDashboardState(): TypeDashboardPaginationState {
    return {
      current: this.eventSourceTablePageCurrent,
      pageSize: this.eventSourceTablePageSize,
      total: this.countDevices,
    };
  }

  // Получение пагинации для таблицы групп
  get groupDashboardState(): TypeDashboardPaginationState {
    return {
      current: this.groupTablePageCurrent,
      pageSize: this.groupTablePageSize,
      total: this.countGroup,
    };
  }

  get getFirewallOnlineStatus(): { [key: number]: FirewallStatus } {
    return toJS(this.firewallStatus);
  }

  // Получение списка устройств для таблицы
  get devicesList(): Array<
    EndpointDevice | ArmaIndustrialFirewall | SensorDevice
  > {
    const devices: Array<
      EndpointDevice | ArmaIndustrialFirewall | SensorDevice
    > = this.rootStore.devicesStore.list.map(
      (device: {
        _listRecord: Array<
          EndpointDevice | ArmaIndustrialFirewall | SensorDevice
        >;
      }) => device._listRecord,
    );

    devices.forEach((device) => {
      // Перебираем и записываем статус фаервола
      if (
        device.type === DeviceType.Firewall &&
        device.id &&
        device.status?.status
      ) {
        this.firewallStatus[device.id] = device.status.status as FirewallStatus;
      }

      // Перебираем и записываем id устройства с его типом
      if (device.id && device.type && device.status) {
        this.devicesTypes[device.id] = device.type;
      }
    });

    return devices;
  }

  get countDevices(): number {
    return this.rootStore.devicesStore.total;
  }

  get countGroup(): number {
    return this.rootStore.tagsStore.totalGroups;
  }

  fetchEventSourceDevices = async (): Promise<void> => {
    await this.rootStore.devicesStore.fetchEventSourceDevices(
      this.eventSourceDashboardState.current,
      this.eventSourceDashboardState.pageSize,
      this.sorterField,
    );
  };

  setTypeSelectedCard = (type: DeviceType | null): void => {
    this.typeSelectedDevice = type;
  };

  get loading(): boolean {
    return this.rootStore.devicesStore.getLoading;
  }

  // Возвращаем устройсто в зависимости от его типа
  get getEventSourceDetails():
    | ArmaIndustrialFirewall
    | EndpointDevice
    | SensorDevice
    | null {
    if (this.typeSelectedDevice === 'endpoint') {
      return toJS(this.rootStore.endpointStore.endpoint);
    } else if (this.typeSelectedDevice === 'firewall') {
      return toJS(this.rootStore.firewallStore.firewall);
    } else if (this.typeSelectedDevice === 'sensor') {
      return toJS(this.rootStore.sensorStore.sensor);
    } else {
      return null;
    }
  }

  cardInfoTitle = (
    locale: {
      newDevice: string;
      copyEndpoint: string;
    },
    form: FormInstance,
  ): string => {
    if (this.isCopyEndpointStatus) {
      return `${locale.copyEndpoint} ${this.nameOfCopiedEndpoint}`;
    } else if (!this.isCopyEndpointStatus && form.getFieldValue('name')) {
      return form.getFieldValue('name');
    } else {
      return locale.newDevice;
    }
  };

  patchFirewallDevice = async (
    data: ArmaIndustrialFirewall,
    id: number,
  ): Promise<void> => {
    await this.rootStore.devicesStore.patchFirewallRecord(data, id);
  };

  patchEndpointDevice = async (
    data: EndpointDevice,
    id: number,
  ): Promise<void> => {
    await this.rootStore.devicesStore.patchEndpointRecord(data, id);
  };

  postFirewallDevice = async (data: ArmaIndustrialFirewall): Promise<void> => {
    await this.rootStore.devicesStore.postFirewallRecord(data);
  };

  postEndpointDevice = async (data: EndpointDevice): Promise<void> => {
    await this.rootStore.devicesStore.postEndpointRecord(data);
  };

  rotationFormField: TypeRotationFormField = {
    event_rotation_period: 0,
    event_rotation_size: 0,
    event_rotation_time: undefined,
    event_rotation_type: 0,
  };

  get getRotationFormField(): TypeRotationFormField {
    if (this.rotationFormField.event_rotation_type === 2) {
      delete this.rotationFormField.event_rotation_period;
      delete this.rotationFormField.event_rotation_time;
      return toJS(this.rotationFormField);
    } else {
      return toJS(this.rotationFormField);
    }
  }

  // Сброс значения ротоции
  resetRotationType = (): void => {
    this.rotationFormField.event_rotation_type = 0;
  };

  // Заполнение FormInstance данными IE
  endpointFillFormData = (form: FormInstance): void => {
    const response = this.rootStore.endpointStore.endpoint;

    if (this.isCopyEndpointStatus) {
      this.nameOfCopiedEndpoint = response?.name;
      delete response?.name;
      delete response?.ip;
      delete response?.port;
      delete response?.id;
    }

    this.rotationFormField = {
      event_rotation_period: response?.event_rotation_period,
      event_rotation_size: response?.event_rotation_size,
      event_rotation_time: moment(response?.event_rotation_time, 'HH:mm:ss'),
      event_rotation_type: response?.event_rotation_type,
    };

    if (response?.scan_paths) {
      this.rootStore.endpointUiStore.setIntegrityControlTablePath(
        response.scan_paths.map((path: string, index: number) => {
          return {
            path,
            id: index,
          };
        }),
      );
    }
    if (response?.antivirus_paths) {
      this.rootStore.endpointUiStore.setAntivirusTablePath(
        response.antivirus_paths.map((path: string, index: number) => {
          return {
            path,
            id: index,
          };
        }),
      );
    }
    if (response?.white_list_paths) {
      this.rootStore.endpointUiStore.setWhiteListTablePathTablePath(
        response.white_list_paths.map((path: string, index: number) => {
          return {
            path,
            id: index,
          };
        }),
      );
    }

    form.setFieldsValue({
      name: response?.name,
      ip: response?.ip,
      port: response?.port,
      id: response?.id,
      description: response?.description,
      integrity_control_enabled: response?.integrity_control_enabled,
      integrity_control_timeout: response?.integrity_control_timeout,
      whitelist_enabled: response?.whitelist_enabled,
      whitelist_admin: response?.whitelist_admin,
      antivirus_enabled: response?.antivirus_enabled,
      antivirus_start_scan: response?.antivirus_start_scan,
      antivirus_remove_infected_files:
        response?.antivirus_remove_infected_files,
      device_control_enabled: response?.device_control_enabled,
      prohibit_cd_access: response?.prohibit_cd_access,
      usb_control_enabled: response?.usb_control_enabled,
      group: response?.group?.id || undefined,
      event_rotation_period: response?.event_rotation_period,
      event_rotation_size: response?.event_rotation_size,
      event_rotation_time: moment(response?.event_rotation_time, 'HH:mm:ss'),
      event_rotation_type: response?.event_rotation_type,
    });
  };

  // Заполнение FormInstance данными IF
  firewallFillFormData = (form: FormInstance): void => {
    const response = this.rootStore.firewallStore.firewall;
    form.setFieldsValue({
      id: response?.id,
      name: response?.name,
      ip: response?.ip,
      key: response?.key,
      secret: response?.secret,
      port: response?.port,
      description: response?.description,
      group: response?.group?.id || undefined,
    });
  };

  // Функция которая выполняет набор действий при клике на Сенсор в таблице
  sensorActionsByOnRowEvent = async (
    id: number,
    form: FormInstance,
  ): Promise<void> => {
    // Очищаем данные ранее выбранного сенсора
    this.rootStore.sensorStore.clearSensorDetailById();

    // Получаем новые данные сенсора по выбранному id
    await this.rootStore.sensorStore.fetchSensorDetailById(id);

    if (
      this.rootStore.sensorStore.getSensorDetailById?.status?.status ===
      'online'
    ) {
      await this.rootStore.sensorStore.fetchSensorInterfacesDetailById(id);
    } else {
      this.rootStore.sensorStore.clearSensorInterfacesById();
    }

    // Заполняем форму данными Сенсора
    this.sensorFillFormData(form);
    this.setTypeSelectedCard(DeviceType.Sensor);
  };

  // Заполнение FormInstance данными IS
  sensorFillFormData = (form: FormInstance): void => {
    const sensorDetailData = this.rootStore.sensorStore.sensor;

    form.setFieldsValue({
      id: sensorDetailData?.id,
      name: sensorDetailData?.name,
      ip: sensorDetailData?.ip,
      port: sensorDetailData?.port,
      description: sensorDetailData?.description,
      authorization_key: sensorDetailData?.authorization_key,
      group: sensorDetailData?.group?.id
        ? sensorDetailData?.group?.id
        : undefined,
      control_interface: sensorDetailData?.control_interface,
      status: sensorDetailData?.status?.status,
      protocols_analysis: sensorDetailData?.protocols_analysis,
      signature_analysis: sensorDetailData?.signature_analysis,
      span_interface: sensorDetailData?.span_interface,
      synchronization: sensorDetailData?.synchronization,
      type: sensorDetailData?.type,
      updated: sensorDetailData?.updated,
      uuid: sensorDetailData?.uuid,
    });
  };

  // Удаление устройства
  deleteDevice = async (id: number[]): Promise<void> => {
    await this.rootStore.devicesStore.deleteDeviceRecord(id);
  };

  // Загрузка конфигурации IF
  downloadConfigFirewall = async (ids: number[]): Promise<void> => {
    await this.rootStore.devicesStore.downloadConfigFirewallId(ids);
  };

  // Загрузка конфигурации IE
  downloadConfigEndpoint = async (id: number): Promise<void> => {
    await this.rootStore.devicesStore.downloadConfigEndpoint(id);
  };

  // Обновление конфигурации IF
  uploadConfigFirewall = async (
    ids: number[],
    data: FormData,
  ): Promise<PromiseSettledResult<unknown>[]> => {
    return this.rootStore.devicesStore.uploadConfigOnFirewall(ids, data);
  };

  // Обновление конфигурации c IE
  updateEndpoint = (
    ids: number[],
  ): Promise<PromiseSettledResult<unknown>[]> => {
    return this.rootStore.devicesStore.uploadConfigEndpoint(ids);
  };

  uploadRulesFirewall = (
    ids: number[],
    data: FormData,
  ): Promise<PromiseSettledResult<TypeUploadedIdsRules>[]> => {
    return this.rootStore.devicesStore.uploadRulesFirewall(ids, data);
  };

  // Функция для загрузки списка групп
  fetchGroups = (): void => {
    const { current, pageSize } = this.groupDashboardState;
    this.rootStore.tagsStore.fetchGroupsList(
      `/devices/groups/?page=${current}&page_size=${pageSize}${this.sorterField}`,
    );
  };

  // Изменение тега
  patchGroupsList = async (data: TypeTags, id: number): Promise<void> => {
    await this.rootStore.tagsStore.patchRecordInGroupsList(
      '/devices/groups/',
      data,
      id,
    );
    this.selectedTag = undefined;
    this.selectedTagId = undefined;
  };

  // Создание тега
  postGroupsList = async (data: TypeTags): Promise<void> => {
    await this.rootStore.tagsStore.postRecordInGroupsList('/devices/groups/', {
      ...data,
      devices: [],
    });
    this.selectedTag = undefined;
    this.selectedTagId = undefined;
  };

  // Изменение тэга и его id
  setSelectedTag = (id: number | null | undefined): void => {
    switch (id) {
      case undefined:
        this.selectedTag = { name: '', description: '' };
        this.selectedTagId = undefined;
        break;
      case null:
        this.selectedTag = undefined;
        this.selectedTagId = undefined;
        break;
      default:
        this.selectedTag = this.rootStore.tagsStore.record(id).tagRecord;
        this.selectedTagId = id;
    }
  };

  get groupList(): TypeTags[] {
    return this.rootStore.tagsStore.list.map((x: { _tagRecord: TypeTags }) => {
      return {
        ...x._tagRecord,
        key: x._tagRecord.id,
      };
    });
  }

  //Возвращение одного тэга по id
  get getSelectedTagId(): number | undefined | null {
    return this.selectedTagId;
  }

  get getSelectedTag(): TypeTagCreate | TypeTags | undefined {
    return toJS(this.selectedTag);
  }

  deleteGroupsRecord = async (id: number[]): Promise<void> =>
    this.rootStore.tagsStore.deleteRecordInGroupsList('/devices/groups/', id);

  get getCheckedColumns(): TUseColumns[] {
    return toJS(this.checkedColumns);
  }

  exportCSV = async (): Promise<void> => {
    await this.rootStore.devicesStore.exportCSV();
  };

  setCheckedColumns = (value: TUseColumns[]): void => {
    this.checkedColumns = value;
  };
}
