import qs from 'qs';

import api from 'src/config/api';
import { type Comment } from 'src/types/comments';
import {
  type Event,
  type EventInvitation,
  type EventInvitationUser,
  type EventOrganizer,
  type EventOrganizerStatus,
  type EventPostType,
  type EventTimeRange,
  type EventUsersStats,
  type InvitableEventOrganizer,
  type InvitationStatus,
} from 'src/types/events';
import { type CursorPagination, type Pagination } from 'src/types/services';
import { type User } from 'src/types/user';
import { formatPagination } from 'src/utils/pagination';

export const getEvents = (
  pagination: { limit: number; page: number },
  timeRange: EventTimeRange,
  invitationStatus: InvitationStatus[] = [],
  onlyInvited?: boolean,
  onlyCreatedByUser?: boolean,
) =>
  api.get<Pagination<Event[]>>('events', {
    params: {
      ...formatPagination(pagination),
      timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
      timeRange,
      invitationStatus: invitationStatus.join(','),
      onlyInvited,
      onlyCreatedByUser,
    },
  });

export const getEvent = (id: number) => api.get<Event>(`events/${id}`);

export const createEvent = (event: Partial<Event>) =>
  api.post<Event>('events', event);

export const createInvitation = (
  eventId: number,
  data: Partial<EventInvitation>,
) => api.post(`events/${eventId}/invitations`, data);

export const getUninvitedUsersCount = (eventId: number, params: object) =>
  api.get<{ count: number }>(`events/${eventId}/invitations/users/count`, {
    params,
    paramsSerializer: value => qs.stringify(value, { arrayFormat: 'comma' }),
  });

export const getEventInvitationSelection = (
  eventId: number,
  search: string,
  selection: object,
  page: number,
) =>
  api.get(`events/${eventId}/invitations/users/selection`, {
    params: {
      page,
      limit: 100,
      search: search || undefined,
      ...selection,
    },
    paramsSerializer: params => qs.stringify(params, { arrayFormat: 'comma' }),
  });

export const getInvitableUsers = (
  eventId: number,
  search: string,
  page: number,
  segmentationItemIds?: number[],
) =>
  api.get<Pagination<User & { isInvited: boolean }>>(
    `events/${eventId}/invitations/users`,
    {
      params: {
        page,
        limit: 100,
        search: search || undefined,
        segmentationItemIds: segmentationItemIds,
      },
      paramsSerializer: params =>
        qs.stringify(params, { arrayFormat: 'comma' }),
    },
  );

export const getEventUserStats = (eventId: number) =>
  api.get<EventUsersStats>(`events/${eventId}/invitations/users/stats`);

export const editEvent = (event: Partial<Event>) =>
  api.put<Event>(`events/${event.id}`, event);

export const deleteEvent = (id: number) => api.delete<Event>(`events/${id}`);

export const answerInvitation = (eventId: number, status: InvitationStatus) =>
  api.put<Event>(`events/${eventId}/invitations`, { status });

export const getInvitations = (
  eventId: number,
  status: InvitationStatus,
  page: number,
) =>
  api.get<Pagination<EventInvitationUser>>(`events/${eventId}/invitations`, {
    params: { status, page, limit: 20 },
  });

export const deleteInvitations = (eventId: number, userId: number) =>
  api.delete(`events/${eventId}/invitations/${userId}`);

export const getEventPosts = (
  eventId: number,
  cursor: string,
  withLivestream?: boolean,
) =>
  api.get<CursorPagination<EventPostType[]>>(`events/${eventId}/posts`, {
    params: {
      limit: 20,
      cursor: cursor || undefined,
      withLivestream: withLivestream,
    },
  });

export const createPost = (eventId: number, post: Partial<EventPostType>) =>
  api.post(`events/${eventId}/posts`, post);

export const editPost = (
  eventId: number,
  postId: number,
  post: Partial<EventPostType>,
) => api.put(`events/${eventId}/posts/${postId}`, post);

export const deletePost = (eventId: number, postId: number) =>
  api.delete(`events/${eventId}/posts/${postId}`);

export const getPost = (eventId: number, postId: number) =>
  api.get(`events/${eventId}/posts/${postId}`);

export const getCalendarEvent = (eventId: number) =>
  api.get(`events/${eventId}/ics`);

export const getEventGuests = (eventId: number) =>
  api.get(`/events/${eventId}/invitations/users/report`);

export const addEventPostReaction = (
  eventId: number,
  postId: number,
  emoji: string,
  unified: string,
) =>
  api.post(`events/${eventId}/posts/${postId}/reactions`, { emoji, unified });

export const removeEventPostReaction = (
  eventId: number,
  postId: number,
  emoji: string,
) =>
  api.delete(`events/${eventId}/posts/${postId}/reactions`, {
    data: { emoji },
  });

export const getEventPostReactionUsers = (
  eventId: number,
  postId: number,
  emoji: string,
  cursor: string,
  limit = 30,
) =>
  api.get<CursorPagination<User[]>>(
    `events/${eventId}/posts/${postId}/reactions/users`,
    { params: { emoji, limit, cursor } },
  );

export const postEventComment = (eventId: number, postId: number, body: any) =>
  api.post<Comment>(`events/${eventId}/posts/${postId}/comments`, body);

export const getEventPostCommentsPaginated = (
  eventId: number,
  postId: number,
  cursor: string | number,
  limit: string | number,
  orderBy: string = 'CREATED_AT',
  order: string = 'DESC',
) =>
  api.get<CursorPagination<Comment[]>>(
    `events/${eventId}/posts/${postId}/comments`,
    {
      params: {
        cursor,
        limit,
        orderBy,
        order,
        childCommentsNumber: 2,
      },
    },
  );

export const getEventChildCommentsPaginated = (
  eventId: number,
  postId: number,
  parentId: number,
  cursor: string,
  limit: number,
) =>
  api.get<CursorPagination<Comment[]>>(
    `events/${eventId}/posts/${postId}/comments`,
    {
      params: {
        cursor,
        limit,
        parentId,
        orderBy: 'CREATED_AT',
        order: 'DESC',
      },
    },
  );

export const updateEventPostComment = (
  eventId: number,
  postId: number,
  commentId: number,
  data: Comment,
) =>
  api.put<Comment>(
    `events/${eventId}/posts/${postId}/comments/${commentId}`,
    data,
  );

export const deleteEventPostComment = (
  eventId: number,
  postId: number,
  commentId: number,
) => api.delete(`events/${eventId}/posts/${postId}/comments/${commentId}`);

export const addEventPostCommentReaction = (
  eventId: number,
  postId: number,
  commentId: number,
  emoji: string,
  unified: string,
) =>
  api.post(
    `events/${eventId}/posts/${postId}/comments/${commentId}/reactions`,
    {
      emoji,
      unified,
    },
  );

export const removeEventPostCommentReaction = (
  eventId: number,
  postId: number,
  commentId: number,
  emoji: string,
) =>
  api.delete(
    `events/${eventId}/posts/${postId}/comments/${commentId}/reactions`,
    {
      data: { emoji },
    },
  );

export const getEventPostCommentReactionUsers = (
  eventId: number,
  postId: number,
  commentId: number,
  emoji: string,
  cursor: string,
  limit = 10,
) =>
  api.get<CursorPagination<User[]>>(
    `events/${eventId}/posts/${postId}/comments/${commentId}/reactions/users`,
    { params: { emoji, limit, cursor } },
  );

export const joinEventSocketRoom = (eventId: number) =>
  api.post<{ ticketId: string }>(`events/${eventId}/room_tickets`);

export const getEventOrganizers = ({
  id,
  limit,
  cursor,
  excludeUserIds,
  userIds,
  statuses,
}: {
  id: number;
  limit?: number;
  cursor?: string;
  excludeUserIds?: number[];
  userIds?: number[];
  statuses?: EventOrganizerStatus[];
}) =>
  api.get<CursorPagination<EventOrganizer[]>>(`events/${id}/organizers`, {
    params: {
      limit,
      cursor,
      excludeUserIds: excludeUserIds?.join(','),
      userIds: userIds?.join(','),
      statuses: statuses?.join(','),
    },
  });

export const getInvitableOrganizers = ({
  id,
  q,
  limit,
  cursor,
}: {
  id: number;
  q?: string;
  limit?: number;
  cursor?: string;
}) =>
  api.get<CursorPagination<InvitableEventOrganizer[]>>(
    `events/${id}/co-organizers/users`,
    {
      params: {
        limit,
        q: q || undefined,
        cursor,
      },
    },
  );

export const getUsers = ({
  groupId,
  q,
  limit,
  cursor,
}: {
  groupId?: number;
  q?: string;
  limit?: number;
  cursor?: string;
}) =>
  api.get<CursorPagination<User[]>>(`events/users`, {
    params: {
      limit,
      q: q || undefined,
      cursor,
      groupId,
    },
  });

export const addEventOrganizer = (eventId: number, userIds: number[]) =>
  api.post(`events/${eventId}/co-organizers`, { userIds });

export const deleteEventOrganizer = (
  eventId: number,
  organizerId: number | string,
) => api.delete(`events/${eventId}/co-organizers/${organizerId}`);

export const acceptOrganizerInvitation = (eventId: number) =>
  api.post(`events/${eventId}/co-organizers/accept`);

export const rejectOrganizerInvitation = (eventId: number) =>
  api.post(`events/${eventId}/co-organizers/reject`);

export const getEventOrganizersCount = ({
  eventId,
  statuses,
}: {
  eventId: number;
  statuses: EventOrganizerStatus[];
}) =>
  api.get<{ count: number }>(`events/${eventId}/organizers/count`, {
    params: {
      statuses: statuses?.join(','),
    },
  });
