import { identity, pickBy } from 'lodash-es';
import qs from 'qs';

import api from 'src/config/api';
import { type Acknowledgement } from 'src/pages/dashboard/acknowledgements/types';
import { type ProfileDataMap } from 'src/types/instance';
import { type Post } from 'src/types/posts';
import {
  type JoinWithInviteData,
  type Segmentation,
  type SegmentationReachResponse,
  type SignUpWithInviteData,
  type User,
  type UserListResponse,
  type UserListSegmentationResponse,
  type UserProfile,
} from 'src/types/user';
import { type PaginatedResponse } from 'src/utils/pagination';
import { addAudienceHeader } from 'src/utils/segmentationUtils';

export const getUserList = (
  search: string,
  page: number,
  limit = 10,
  filterSelf: boolean = false,
  notIncludingIds: number[] = [],
  orderBy = 'NAME',
  order = 'ASC',
  status?: string,
  isAgent?: boolean,
) =>
  api.get<UserListResponse>('/users/paginated', {
    params: {
      page,
      limit,
      search: search || undefined,
      filterSelf,
      notIncludingIds,
      orderBy,
      order,
      status,
      isAgent,
    },
    paramsSerializer: params => qs.stringify(params, { arrayFormat: 'comma' }),
  });

export const getPublicUsers = (params: {
  search?: string;
  page: number;
  limit: number;
  ids?: number[];
  segmentationItemIds?: number[];
  isAgent?: boolean;
  excludeOfflineUsers?: boolean;
}) =>
  api.get<PaginatedResponse<User>>('users/public', {
    params: pickBy(
      {
        ...params,
        ids: params.ids?.toString(),
        segmentationItemIds: params.segmentationItemIds?.toString(),
        isAgent: params.isAgent?.toString(),
      },
      identity,
    ),
  });

export const getPeopleList = (
  q: string,
  page: number,
  limit = 10,
  orderBy?: string,
  order?: string,
) =>
  api.get<UserListResponse>('/people', {
    params: {
      page,
      limit,
      q: q || undefined,
      orderBy: orderBy || undefined,
      order: order || undefined,
    },
    paramsSerializer: params => qs.stringify(params, { arrayFormat: 'comma' }),
  });

export const getUserListByIds = (
  ids: number[],
  page: number = 1,
  limit: number = 100,
) =>
  api.get<UserListResponse>('/users/paginated', {
    params: {
      page,
      limit,
      ids: ids?.toString(),
      filterSelf: false,
    },
  });

export const getUserListSegmentation = (
  params: {
    segmentationItemIds: string;
    includeLoggedUser: boolean;
    page: number;
    limit: number;
  },
  useAudienceApi = false,
) => {
  const {
    segmentationItemIds = '',
    includeLoggedUser = false,
    page = 1,
    limit = 1,
  } = params;
  return api.get<UserListSegmentationResponse>('/users/audience', {
    params: {
      page,
      limit,
      segmentationItemIds,
      includeLoggedUser,
      orderBy: 'NAME',
      order: 'ASC',
    },
    headers: addAudienceHeader(useAudienceApi),
  });
};

export const getAmountUsersReachSegmentation = async (
  params: {
    instanceId: number;
    segmentationItemIds: string;
    includeLoggedUser: boolean;
    page?: number;
    limit?: number;
  },
  useAudienceApi = false,
) => {
  const {
    instanceId,
    segmentationItemIds = '',
    includeLoggedUser = false,
    page = 1,
    limit = 1,
  } = params;
  if (segmentationItemIds) {
    const response = await api.get<UserListSegmentationResponse>(
      '/users/audience/count',
      {
        params: {
          page,
          limit,
          segmentationItemIds,
          includeLoggedUser,
        },
        headers: addAudienceHeader(useAudienceApi),
      },
    );

    return response.data.count;
  }

  const response = await api.get<SegmentationReachResponse>(
    `/instances/${instanceId}/user-stats`,
  );

  return response.data.total;
};

export const getUserListToAcknowledge = (
  search: string,
  page: number,
  limit = 100,
) =>
  search
    ? api.get<UserListResponse>('/users/acknowledgeable-users', {
        params: { page, search, limit },
      })
    : api.get<UserListResponse>('/users/acknowledgeable-users', {
        params: { page, limit },
      });

export const getProfileById = (id: number | string) =>
  api.get<User>(`users/${id}`);

export const getUserProfile = (id: number | string) =>
  api.get<UserProfile>(`users/${id}/profile`);

export const getUserPostList = (id: number | string, timestamp: string) =>
  timestamp
    ? api.get<Post[]>(`users/${id}/posts`, { params: { timestamp } })
    : api.get<Post[]>(`users/${id}/posts`);

export const getUserAcknowledgementList = (
  id: number | string,
  timestamp: string,
  limit = 10,
) =>
  timestamp
    ? api.get<Acknowledgement[]>(`users/${id}/received-acknowledgements`, {
        params: { timestamp, limit },
      })
    : api.get<Acknowledgement[]>(`users/${id}/received-acknowledgements`, {
        params: { limit },
      });

export const getUserBosses = (userId: number | string) =>
  api.get<UserListResponse>(`/organization-charts/${userId}/bosses`);

export const changeLanguageUser = (
  id: number,
  language: string,
  headers = {},
) => api.put(`/users/${id}/language`, { language }, { ...headers });

export const sendInvitation = (emails: { emails: string[] }) =>
  api.post('/users/invite', emails);

export const dynamicFieldsResponse = (instanceId: number) =>
  api.get<ProfileDataMap>(`/instances/${instanceId}/profile-fields`);

export const getUserSegmentation = (userId: number | string) =>
  api.get<Segmentation[]>(`/users/${userId}/segmentations`);

export const signUpWithInvite = ({
  firstName,
  inviteCode,
  orgName,
  lastName,
  language,
  passwordInput,
  repeatPasswordInput,
}: SignUpWithInviteData) =>
  api.post(
    '/users/invite/sign-up',
    {
      firstName,
      inviteCode,
      orgName,
      lastName,
      language,
      password: passwordInput,
      repeatPassword: repeatPasswordInput,
    },
    {
      skipInterceptor: true, // sign-up from invite (invite token)
    },
  );

export const joinWithInvite = ({
  firstName,
  lastName,
  inviteCode,
  language,
  passwordInput,
  repeatPasswordInput,
  employeeInternalId,
  orgName,
}: JoinWithInviteData) =>
  api.post(
    '/instances/users',
    {
      firstName,
      lastName,
      inviteCode,
      language,
      passwordInput,
      repeatPasswordInput,
      orgName,
      employeeInternalId,
      password: passwordInput,
      repeatPassword: repeatPasswordInput,
    },
    {
      skipInterceptor: true, // join from invite (invite token)
    },
  );

export const patchUser = (id: number, data: Partial<User>) =>
  api.patch<User>(`users/${id}`, data);

export const patchUserProfileData = (id: number, data: object) =>
  api.patch<User>(`users/${id}/profile-fields`, data);

export const patchUserLanguage = (
  postTranslationLanguage: string,
  userId: number,
) => {
  return api.patch<User>(`users/${userId}`, { postTranslationLanguage });
};

// TIME TRACKING

type TimeTrackingUserSettings = {
  createdAt: string;
  id: string;
  instanceId: number;
  kioskPin: string | null;
  updatedAt: string;
  userId: number;
  hasKioskEnabledPolicy: boolean;
};

export const getLoggedUserTimeTrackingSettings = () =>
  api.get<TimeTrackingUserSettings>(`/time-tracking/user-setting/`);
