import { pickBy } from 'lodash-es';

import { queryClient } from 'src/config/react-query';
import { PROFILE_DATA_CONSTANTS } from 'src/constants/instance';
import { useAuth } from 'src/contexts/JWTContext';
import { profileKeys } from 'src/pages/dashboard/profile/queries';
import {
  getProfileById,
  getUserList,
  getUserListToAcknowledge,
} from 'src/services/users';
import { getUserListSubordinatesForVacations } from 'src/services/vacations';
import { ChatableType } from 'src/types/chats';
import {
  ActionTagUser,
  KEYS,
  type TaggedUser,
  type User,
  type UserDictionaryItem,
} from 'src/types/user';
import { type UserPermissions } from 'src/utils/permissions';

import { peopleSearchKeys } from 'src/components/dashboard/people/queries';
import { userKeys } from 'src/components/dashboard/users/queries';

const LIMIT = 20;
const PAGE = 1;

export const getFullName = (
  user: {
    firstName?: string;
    lastName?: string;
  } | null,
) => {
  if (!user) return '';

  return [user.firstName, user.lastName]
    .filter(str => (str?.length ?? 0) > 0)
    .join(' ')
    .trim();
};

export const permissionsObjectToArray = (
  userPermissions: string[] | Record<string, boolean> | null | undefined,
) => {
  if (Array.isArray(userPermissions))
    return userPermissions as UserPermissions[];
  return Object.keys(pickBy(userPermissions ?? {})) as UserPermissions[];
};

const firstLetterUpper = (word: string) => word.charAt(0).toUpperCase();

const { USER } = ChatableType;

const CHANNELS = 'CHANNELS';

export const getChatablesForList = (chatables: any[], oldChatables: any[]) => {
  let response = [...oldChatables];

  chatables?.forEach(({ type, user, topic }) => {
    const isUser = type === USER;
    const newElem = isUser ? { ...user, type } : { ...topic, type };
    if (response.length === 0) {
      response = [
        {
          character: isUser ? firstLetterUpper(user.firstName) : CHANNELS,
          chatables: [newElem],
        },
      ];
    } else if (
      isUser
        ? response[response.length - 1].character ===
          firstLetterUpper(user.firstName)
        : response[response.length - 1].character === CHANNELS
    ) {
      response[response.length - 1].chatables = [
        ...response[response.length - 1].chatables,
        newElem,
      ];
    } else {
      response = [
        ...response,
        {
          character: isUser ? firstLetterUpper(user.firstName) : CHANNELS,
          chatables: [newElem],
        },
      ];
    }
  });

  return response;
};

export const getUsersForSectionList = (
  users: User[],
  oldUsers: UserDictionaryItem[] = [],
): UserDictionaryItem[] => {
  let response = [...oldUsers];

  users?.forEach(user => {
    if (response.length === 0) {
      response = [
        {
          character: firstLetterUpper(user.firstName),
          users: [user],
        },
      ];
    } else if (
      response[response.length - 1].character ===
      firstLetterUpper(user.firstName)
    ) {
      response[response.length - 1].users = [
        ...response[response.length - 1].users,
        user,
      ];
    } else {
      response = [
        ...response,
        {
          character: firstLetterUpper(user.firstName),
          users: [user],
        },
      ];
    }
  });

  return response;
};

export const getInitials = (fullName: string): string => {
  if (!fullName) return '';

  const initalLetters = fullName
    .split(/(\s+)/)
    .filter(e => e.trim().length > 0);
  let result = '';

  for (let i = 0; i < Math.min(initalLetters.length, 2); i++) {
    result += initalLetters[i].charAt(0);
  }

  return result.toUpperCase();
};

export const CUSTOM_FIELD_DEFAULT_VALUE_MAP = {
  [PROFILE_DATA_CONSTANTS.DATE]: null,
  [PROFILE_DATA_CONSTANTS.STRING]: '',
  [PROFILE_DATA_CONSTANTS.STRING_LIST]: [],
  [PROFILE_DATA_CONSTANTS.USER]: [],
  [PROFILE_DATA_CONSTANTS.USER_LIST]: [],
  [PROFILE_DATA_CONSTANTS.NUMBER]: '',
  [PROFILE_DATA_CONSTANTS.NUMBER_LIST]: [],
  [PROFILE_DATA_CONSTANTS.OPTION]: null,
  [PROFILE_DATA_CONSTANTS.MULTIPLE_OPTION]: [],
};

export const getTaggedUserData = async (userId: number) => {
  try {
    const response = await queryClient.fetchQuery(
      userKeys.detail(userId),
      () => getProfileById(userId),
      {
        staleTime: 120000,
      },
    );

    return response?.data;
  } catch (error) {
    return null;
  }
};

export const getTaggedUserPosition = (user: User, text: string) =>
  text?.search(getFullName(user)) - 1;

export const putCaretInCorrectPosition = (
  { user, tagUserStartPosition, action }: any,
  input: HTMLInputElement,
  startPositionSelectedText: number,
  lastKey: string,
  selectedText = '',
) => {
  if (action === ActionTagUser.ADDUSER) {
    const nameUser = getFullName(user);
    const positionCursor = nameUser.length + tagUserStartPosition + 1;
    input.setSelectionRange(positionCursor, positionCursor);
  } else {
    if (selectedText) {
      if (lastKey === KEYS.BACKSPACE) {
        input.setSelectionRange(
          startPositionSelectedText,
          startPositionSelectedText,
        );
      } else {
        input.setSelectionRange(
          startPositionSelectedText + 1,
          startPositionSelectedText + 1,
        );
      }
    } else {
      input.setSelectionRange(tagUserStartPosition, tagUserStartPosition);
    }
  }
};

export const getTaggedUsers = (users: User[]) => {
  const taggedUsers: TaggedUser[] = [];

  users?.forEach(user => {
    !!user && taggedUsers.push(getTaggedUser(user)!);
  });

  return taggedUsers;
};

export const getTaggedUser = (user: User, start: number = 0) => {
  if (!user) return null;

  return {
    start,
    length: getTaggedUserLength(user),
    type: {
      user: {
        id: user?.id,
      },
    },
  } as TaggedUser;
};

export const getTaggedUserLength = (user: User) => {
  if (!user) return 0;

  return user.firstName.length + user.lastName.length + 2;
};

export const getQueryParamsAutocompleteUser = (
  debouncedQuery: string,
  needSubordinates: boolean,
  needAcknowledgeds: boolean,
) => {
  const { user } = useAuth();

  if (needSubordinates) {
    return {
      queryFn: () =>
        getUserListSubordinatesForVacations(
          user!.id,
          debouncedQuery,
          PAGE,
          LIMIT,
        ),
      queryKey: profileKeys.userListSubordinates(debouncedQuery),
    };
  }

  if (needAcknowledgeds) {
    return {
      queryFn: () => getUserListToAcknowledge(debouncedQuery, PAGE, LIMIT),
      queryKey: peopleSearchKeys.acknowledgementsSearchPeople(debouncedQuery),
    };
  }

  return {
    queryFn: () => getUserList(debouncedQuery, PAGE, LIMIT, false),
    queryKey: profileKeys.userList(debouncedQuery),
  };
};
