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


import { type AuditRouteSearch } from '@/app/router/routes/audit';
import { EquipmentModel } from '@/features/Settings/selects/lib';
import { useGetLocationChildrenQuery } from '@/shared/api/location/client';
import { useAutocompleteDebounce } from '@/shared/hooks';
import { Helpers } from '@/shared/lib';
import { ChangeEvent, useCallback, useEffect, useMemo, useRef } from 'react';

type ModelSelectValue = string | number | boolean | null;
type ModelSelectChangeValue = ModelSelectValue | ModelSelectValue[];

type Params = {
  searchParams: AuditRouteSearch;
  updateParamAndResetPage: (paramName: string, value: unknown) => void;
};

const getEquipmentModelType = (type?: string) => {
  if (!type) {
    return undefined;
  }

  if (type.startsWith('controller_')) {
    return EquipmentModel.controller;
  }

  if (type.startsWith('padlet_')) {
    return EquipmentModel.padlet;
  }

  if (
    type.startsWith('device_') ||
    type.startsWith('network_device_') ||
    type.startsWith('offline_device_')
  ) {
    return EquipmentModel.device;
  }

  return undefined;
};

export const useAdditionalFilters = ({
  searchParams,
  updateParamAndResetPage,
}: Params) => {
  const equipmentModelType = useMemo(
    () => getEquipmentModelType(searchParams.type),
    [searchParams.type],
  );

  const isEquipmentFiltersAvailable = Boolean(equipmentModelType);

  const {
    inputValue: macValue,
    setInputValue: setMacValue,
    debouncedValue: debouncedMac,
    onInputChange: handleMacInputChange,
  } = useAutocompleteDebounce(searchParams.mac || '');

  const {
    inputValue: ipValue,
    setInputValue: setIpValue,
    debouncedValue: debouncedIp,
    onInputChange: handleIpInputChange,
  } = useAutocompleteDebounce(searchParams.ip || '');

  const isMacDebounceReady = useRef(false);
  const isIpDebounceReady = useRef(false);

  useEffect(() => {
    if (!isMacDebounceReady.current) {
      isMacDebounceReady.current = true;
      return;
    }

    updateParamAndResetPage('mac', debouncedMac || undefined);
  }, [debouncedMac, updateParamAndResetPage]);

  useEffect(() => {
    if (!isIpDebounceReady.current) {
      isIpDebounceReady.current = true;
      return;
    }

    updateParamAndResetPage('ip', debouncedIp || undefined);
  }, [debouncedIp, updateParamAndResetPage]);

  const { data: roomsData } = useGetLocationChildrenQuery(
    {
      parentId: Helpers.convertStringsToNumbers(searchParams.floorId),
    },
    {
      skip: !searchParams.floorId.length,
      refetchOnMountOrArgChange: true,
    },
  );

  const roomIdByTreeId = useMemo(() => {
    const rooms = roomsData || [];

    return new Map(
      rooms
        .filter((room) => room.id && room.treeId)
        .map((room) => [String(room.treeId), String(room.id)]),
    );
  }, [roomsData]);

  const clearLocationIds = useCallback(() => {
    updateParamAndResetPage('locationIds', []);
  }, [updateParamAndResetPage]);

  const setRegionId = useCallback(
    (value: string[]) => {
      updateParamAndResetPage('regionId', value);
      clearLocationIds();
    },
    [clearLocationIds, updateParamAndResetPage],
  );

  const setCityId = useCallback(
    (value: string[]) => {
      updateParamAndResetPage('cityId', value);
      clearLocationIds();
    },
    [clearLocationIds, updateParamAndResetPage],
  );

  const setPlaceId = useCallback(
    (value: string[]) => {
      updateParamAndResetPage('placeId', value);
      clearLocationIds();
    },
    [clearLocationIds, updateParamAndResetPage],
  );

  const setFloorId = useCallback(
    (value: string[]) => {
      updateParamAndResetPage('floorId', value);
      clearLocationIds();
    },
    [clearLocationIds, updateParamAndResetPage],
  );

  const setRoomId = useCallback(
    (roomTreeIds: string[]) => {
      const locationIds = roomTreeIds
        .map((treeId) => roomIdByTreeId.get(String(treeId)))
        .filter((id): id is string => Boolean(id));

      updateParamAndResetPage('roomId', roomTreeIds);
      updateParamAndResetPage('locationIds', locationIds);
    },
    [roomIdByTreeId, updateParamAndResetPage],
  );

  const handleChangeModels = useCallback(
    (value: ModelSelectChangeValue) => {
      updateParamAndResetPage(
        'modelIds',
        Array.isArray(value) ? value.map(String) : [],
      );
    },
    [updateParamAndResetPage],
  );

  const handleMacChange = useCallback(
    (event: ChangeEvent<HTMLInputElement>) => {
      handleMacInputChange(event.target.value);
    },
    [handleMacInputChange],
  );

  const handleIpChange = useCallback(
    (value: string) => {
      handleIpInputChange(value);
    },
    [handleIpInputChange],
  );

  const resetAdditionalFilters = useCallback(() => {
    setMacValue('');
    setIpValue('');

    updateParamAndResetPage('modelIds', []);
    updateParamAndResetPage('mac', undefined);
    updateParamAndResetPage('ip', undefined);
    updateParamAndResetPage('locationIds', []);
    updateParamAndResetPage('regionId', []);
    updateParamAndResetPage('cityId', []);
    updateParamAndResetPage('placeId', []);
    updateParamAndResetPage('floorId', []);
    updateParamAndResetPage('roomId', []);
  }, [setIpValue, setMacValue, updateParamAndResetPage]);

  return {
    isEquipmentFiltersAvailable,
    equipmentModelType,

    modelIds: searchParams.modelIds,
    macValue,
    ipValue,

    cityId: searchParams.cityId,
    floorId: searchParams.floorId,
    placeId: searchParams.placeId,
    regionId: searchParams.regionId,
    roomId: searchParams.roomId,

    setRegionId,
    setCityId,
    setPlaceId,
    setFloorId,
    setRoomId,

    handleChangeModels,
    handleMacChange,
    handleIpChange,
    resetAdditionalFilters,
  };
};