import { request } from '../../../utils';
import { API } from '../../../types';
import { ResponseType } from '../response-type';
import { User } from '@api/regions';

export interface PostSearchUsersReturn extends ResponseType {
  data: {
    user_id: number;
    first_name: string;
    last_name: string;
    avatar: string | null;
  }[];
}

// status: 1 -sent; 2 -received; 3 -read; 4 - deleted
export interface PostGetChatsListReturn extends ResponseType {
  conversations: {
    uid: number | null;
    group_chat_token: string | null;
    name: string;
    avatar: string | null;
    short: string;
    sent_by: number;
    updated: Date;
    status: 1 | 2 | 3 | 4;
    unread_count: number;
    last_message_id: number;
    pin: 0 | 1;
    pin_order: number;
    archive: 0 | 1;
    archive_order: number;
    attachement_name: string;
    encrypted: 0 | 1;
    muted: 0 | 1;
    user_type: 'normal' | 'not_exist' | 'blocked';
    can_send_message: 0 | 1;
    is_admin: 0 | 1;
    announcement: 0 | 1;
  }[];
}

export interface PostGetGroupSettingsReturn extends ResponseType {
  settings: {
    members_can_add_new_members: 0 | 1;
    members_can_edit_settings: 0 | 1;
    members_can_send_messages: 0 | 1;
    members_can_see_members: 0 | 1;
    name: string;
    description: string | null;
    avatar: string | null;
    avatar_full: string | null;
    admin: 0 | 1;
    member_count: number;
    muted: 0 | 1;
    description_html?: string;
  };
}

export interface PostGetGroupMembersReturn extends ResponseType {
  settings: {
    uid: number;
    name: string;
    avatar: string | null;
    admin: 0 | 1;
    added: string;
    ranking_data: User;
  }[];
}

export interface PostCanCreateGroupReturn extends ResponseType {
  authorized: 0 | 1;
}

export interface PostCanSendMessageReturn extends ResponseType {
  need_authentication_or_friend?: 0 | 1;
}

interface Attachement {
  id: number;
  filename: string;
  filetype: string;
  attachment_small_url?: string;
  attachment_full_url?: string;
  lat?: number;
  lng?: number;
  attachment_link?: string;
}

export interface Message {
  id: number;
  sender: number;
  recipient: number;
  text: string;
  status: 1 | 2 | 3 | 4;
  sent_datetime: Date;
  received_datetime: Date | null;
  read_datetime: Date | null;
  reply_to_id: number;
  reactions: string;
  edits: string;
  attachement: -1 | Attachement;
  encrypted: 0 | 1;
  isSending?: boolean;
}

interface GroupMessage {
  id: number;
  sender: number;
  recipient: number;
  text: string;
  status: 1 | 2 | 3 | 4;
  sent_datetime: Date;
  received_datetime: Date | null;
  read_datetime: Date | null;
  reply_to_id: number;
  reactions: string;
  edits: string;
  attachement: -1 | Attachement;
  encrypted: 0 | 1;
  sender_avatar: string | null;
  sender_name: string;
  isSending?: boolean;
}

export interface PostGetChatWithReturn extends ResponseType {
  messages: (Message & {
    reply_to: Message;
  })[];
}

export interface PostGetGroupChatWithReturn extends ResponseType {
  groupToken: string;
  groupAvatar: string | null;
  can_send_messages: boolean;
  messages: (GroupMessage & {
    reply_to: GroupMessage;
    sender_avatar: string | null;
    sender_name: string;
  })[];
}

export interface PostSendMessage {
  token: string;
  to_uid: number;
  text: string;
  reply_to_id?: number;
  attachment?: { uri: string; type: string; name?: string } | -1;
}

export interface PostSendGroupMessage {
  token: string;
  to_group_token: string;
  text: string;
  reply_to_id?: number;
  attachment?: { uri: string; type: string; name?: string } | -1;
}

export interface PostSendMessageReturn extends ResponseType {
  message_id: number;
  attachment?: any;
  need_authentication_or_friend?: 0 | 1;
}

export interface PostMessagesReceivedOrRead {
  token: string;
  from_user: number;
  messages_id: number[];
}

export interface PostGroupMessagesReceivedOrRead {
  token: string;
  group_token: string;
  messages_id: number[];
}

export interface PostReactToMessage {
  token: string;
  message_id: number;
  reaction: string;
  conversation_with_user: number;
}

export interface PostUnreactToMessage {
  token: string;
  message_id: number;
  conversation_with_user: number;
}

export interface PostReactToGroupMessage {
  token: string;
  message_id: number;
  reaction: string;
  group_token: string;
}

export interface PostUnreactToGroupMessage {
  token: string;
  message_id: number;
  group_token: string;
}

export interface PostDeleteMessage {
  token: string;
  message_id: number;
  conversation_with_user: number;
}

export interface PostDeleteGroupMessage {
  token: string;
  message_id: number;
  group_token: string;
}

export interface PostEditMessage {
  token: string;
  message_id: number;
  to_uid: number;
  text: string;
}

export interface PostEditGroupMessage {
  token: string;
  message_id: number;
  group_token: string;
  text: string;
}

export interface PostDeleteChat {
  token: string;
  conversation_with_user: number;
}

export interface PostReportConversation {
  token: string;
  reported_user_id: number;
}

export interface PostSetSettings {
  token: string;
  value: 0 | 1;
  conversation_with_user: number;
}

export interface PostSetGroupSettings {
  token: string;
  value: 0 | 1;
  group_token: string;
}

export interface PostGetBlockedReturn extends ResponseType {
  blocked: {
    id: number;
    first_name: string;
    last_name: string;
    avatar: string | null;
  }[];
}

export interface PostGetUnreadCountReturn extends ResponseType {
  unread_conversations: number;
}

export interface PostCreateGroup {
  token: string;
  users: number[];
  name: string;
  admins: number[] | [];
  description?: string;
  group_avatar?: { uri: string; type: string; name?: string };
  members_can_edit_settings?: 0 | 1;
  members_can_add_new_members?: 0 | 1;
  members_can_send_messages?: 0 | 1;
}

export interface PostCreateGroupReturn extends ResponseType {
  groupToken: string;
  groupAvatar: string | null;
  can_send_messages: boolean;
}

export interface PostUpdateGroupSettings {
  token: string;
  group_token: string;
  members_can_edit_settings?: 0 | 1;
  members_can_add_new_members?: 0 | 1;
  members_can_send_messages?: 0 | 1;
  members_can_see_members?: 0 | 1;
  name?: string;
  description?: string;
  group_avatar?: { uri: string; type: string; name?: string };
}

export interface PostGetGroupMessageStatusReturn {
  result: string;
  status: {
    uid: number;
    name: string;
    avatar: string | null;
    status: 1 | 2 | 3 | 4;
    datetime: string | null;
  }[];
}

export interface PostGetPinnedGroupMessageReturn extends ResponseType {
  message: GroupMessage;
  pinned_by: {
    uid: number;
    name: string;
    avatar: string | null;
  };
  pinned_time: string;
}

export const chatApi = {
  searchUsers: (token: string, search: string) =>
    request.postForm<PostSearchUsersReturn>(API.SEARCH_USERS, { token, search }),
  getChatsList: (token: string, archive: 0 | 1) =>
    request.postForm<PostGetChatsListReturn>(API.GET_CHATS_LIST, { token, archive }),
  getChatWith: (
    token: string,
    uid: number,
    no_of_messages: number,
    previous_than_message_id: number
  ) =>
    request.postForm<PostGetChatWithReturn>(API.GET_CHAT_WITH, {
      token,
      uid,
      no_of_messages,
      previous_than_message_id
    }),
  getChatWithAll: (token: string, uid: number) =>
    request.postForm<PostGetChatWithReturn>(API.GET_CONVERSATION_WITH_ALL, {
      token,
      uid
    }),
  getGroupChatAll: (token: string, group_token: string) =>
    request.postForm<PostGetGroupChatWithReturn>(API.GET_GROUP_CONVERSATION_ALL, {
      token,
      group_token
    }),
  sendMessage: (data: PostSendMessage) => {
    const formData = new FormData();
    formData.append('token', data.token);
    formData.append('to_uid', data.to_uid.toString());
    formData.append('text', data.text);
    if (data.reply_to_id && data.reply_to_id !== undefined) {
      formData.append('reply_to_id', data.reply_to_id.toString());
    }
    if (data.attachment && data.attachment !== -1) {
      const { uri, type, name } = data.attachment;
      formData.append('attachment', {
        uri,
        type: type === 'image' ? type + '/' + uri.split('.').pop()! : type,
        name: name || 'file'
      } as unknown as Blob);
    }

    return request.postForm<PostSendMessageReturn>(API.SEND_MESSAGE, formData);
  },
  messagesReceived: (data: PostMessagesReceivedOrRead) =>
    request.postForm<ResponseType>(API.MESSAGES_RECEIVED, data),
  messagesRead: (data: PostMessagesReceivedOrRead) =>
    request.postForm<ResponseType>(API.MESSAGES_READ, data),
  reactToMessage: (data: PostReactToMessage) =>
    request.postForm<ResponseType>(API.REACT_TO_MESSAGE, data),
  deleteMessage: (data: PostDeleteMessage) =>
    request.postForm<ResponseType>(API.DELETE_MESSAGE, data),
  setPin: (data: PostSetSettings) => request.postForm<ResponseType>(API.SET_PIN, data),
  setArchive: (data: PostSetSettings) => request.postForm<ResponseType>(API.SET_ARCHIVE, data),
  setBlock: (data: PostSetSettings) => request.postForm<ResponseType>(API.SET_BLOCK, data),
  setMute: (data: PostSetSettings) => request.postForm<ResponseType>(API.SET_MUTE, data),
  deleteChat: (data: PostDeleteChat) => request.postForm<ResponseType>(API.DELETE_CHAT, data),
  unreactToMessage: (data: PostUnreactToMessage) =>
    request.postForm<ResponseType>(API.UNREACT_TO_MESSAGE, data),
  getBlocked: (token: string) => request.postForm<PostGetBlockedReturn>(API.GET_BLOCKED, { token }),
  getUnreadMessagesCount: (token: string) =>
    request.postForm<PostGetUnreadCountReturn>(API.GET_UNREAD_MESSAGES_PRESENT, {
      token
    }),
  reportConversation: (data: PostReportConversation) =>
    request.postForm<ResponseType>(API.REPORT_CONVERSATION, data),
  createGroup: (data: PostCreateGroup) => {
    const formData = new FormData();

    formData.append('token', data.token);
    formData.append('users', JSON.stringify(data.users));
    formData.append('name', data.name);

    if (data.description) {
      formData.append('description', data.description);
    }
    if (data.hasOwnProperty('members_can_edit_settings')) {
      formData.append('members_can_edit_settings', JSON.stringify(data.members_can_edit_settings));
    }
    if (data.hasOwnProperty('members_can_send_messages')) {
      formData.append('members_can_send_messages', JSON.stringify(data.members_can_send_messages));
    }
    if (data.hasOwnProperty('members_can_add_new_members')) {
      formData.append(
        'members_can_add_new_members',
        JSON.stringify(data.members_can_add_new_members)
      );
    }

    formData.append('admins', JSON.stringify(data.admins));

    if (data.group_avatar) {
      const { uri, type, name } = data.group_avatar;
      formData.append('group_avatar', {
        uri,
        type: type === 'image' ? type + '/' + uri.split('.').pop()! : type,
        name: name || 'avatar'
      } as unknown as Blob);
    }

    return request.postForm<PostCreateGroupReturn>(API.CREATE_GROUP, formData);
  },
  getGroupChat: (
    token: string,
    group_token: string,
    no_of_messages: number,
    previous_than_message_id: number
  ) =>
    request.postForm<PostGetGroupChatWithReturn>(API.GET_GROUP_CHAT, {
      token,
      group_token,
      no_of_messages,
      previous_than_message_id
    }),
  sendGroupMessage: (data: PostSendGroupMessage) => {
    const formData = new FormData();
    formData.append('token', data.token);
    formData.append('to_group_token', data.to_group_token);
    formData.append('text', data.text);
    if (data.reply_to_id && data.reply_to_id !== undefined) {
      formData.append('reply_to_id', data.reply_to_id.toString());
    }
    if (data.attachment && data.attachment !== -1) {
      const { uri, type, name } = data.attachment;
      formData.append('attachment', {
        uri,
        type: type === 'image' ? type + '/' + uri.split('.').pop()! : type,
        name: name || 'file'
      } as unknown as Blob);
    }

    return request.postForm<PostSendMessageReturn>(API.SEND_GROUP_MESSAGE, formData);
  },
  groupMessagesReceived: (data: PostGroupMessagesReceivedOrRead) =>
    request.postForm<ResponseType>(API.GROUP_MESSAGES_RECEIVED, data),
  groupMessagesRead: (data: PostGroupMessagesReceivedOrRead) =>
    request.postForm<ResponseType>(API.GROUP_MESSAGES_READ, data),
  reactToGroupMessage: (data: PostReactToGroupMessage) =>
    request.postForm<ResponseType>(API.REACT_TO_GROUP_MESSAGE, data),
  unreactToGroupMessage: (data: PostUnreactToGroupMessage) =>
    request.postForm<ResponseType>(API.UNREACT_TO_GROUP_MESSAGE, data),
  deleteGroupMessage: (data: PostDeleteGroupMessage) =>
    request.postForm<ResponseType>(API.DELETE_GROUP_MESSAGE, data),
  setPinForGroup: (data: PostSetGroupSettings) =>
    request.postForm<ResponseType>(API.SET_PIN_FOR_GROUP, data),
  setArchiveForGroup: (data: PostSetGroupSettings) =>
    request.postForm<ResponseType>(API.SET_ARCHIVE_FOR_GROUP, data),
  setMuteForGroup: (data: PostSetGroupSettings) =>
    request.postForm<ResponseType>(API.SET_MUTE_FOR_GROUP, data),
  leaveGroup: (token: string, group_token: string) =>
    request.postForm<ResponseType>(API.LEAVE_GROUP, { token, group_token }),
  addToGroup: (token: string, uid: number, group_token: string) =>
    request.postForm<ResponseType>(API.ADD_TO_GROUP, { token, uid, group_token }),
  addToGroupAsAdmin: (token: string, uid: number, group_token: string) =>
    request.postForm<ResponseType>(API.ADD_TO_GROUP_AS_ADMIN, { token, uid, group_token }),
  setGroupAdmin: (token: string, uid: number, group_token: string, value: 0 | 1) =>
    request.postForm<ResponseType>(API.SET_GROUP_ADMIN, { token, uid, group_token, value }),
  removeFromGroup: (token: string, uid: number, group_token: string) =>
    request.postForm<ResponseType>(API.REMOVE_FROM_GROUP, { token, uid, group_token }),
  getGroupSettings: (token: string, group_token: string) =>
    request.postForm<PostGetGroupSettingsReturn>(API.GET_GROUP_SETTINGS, { token, group_token }),
  getGroupMembers: (token: string, group_token: string) =>
    request.postForm<PostGetGroupMembersReturn>(API.GET_GROUP_MEMBERS, { token, group_token }),
  updateGroupSettings: (data: PostUpdateGroupSettings) => {
    const formData = new FormData();

    formData.append('token', data.token);
    formData.append('group_token', data.group_token);

    if (data.hasOwnProperty('members_can_edit_settings')) {
      formData.append('members_can_edit_settings', JSON.stringify(data.members_can_edit_settings));
    }
    if (data.hasOwnProperty('members_can_add_new_members')) {
      formData.append(
        'members_can_add_new_members',
        JSON.stringify(data.members_can_add_new_members)
      );
    }
    if (data.hasOwnProperty('members_can_send_messages')) {
      formData.append('members_can_send_messages', JSON.stringify(data.members_can_send_messages));
    }
    if (data.hasOwnProperty('members_can_see_members')) {
      formData.append('members_can_see_members', JSON.stringify(data.members_can_see_members));
    }
    if (data.name) {
      formData.append('name', data.name);
    }
    if (data.description) {
      formData.append('description', data.description);
    }

    if (data.group_avatar) {
      const { uri, type, name } = data.group_avatar;
      formData.append('group_avatar', {
        uri,
        type: type === 'image' ? type + '/' + uri.split('.').pop()! : type,
        name: name || 'avatar'
      } as unknown as Blob);
    }

    return request.postForm<ResponseType>(API.UPDATE_GROUP_SETTINGS, formData);
  },
  getGroupMessageStatus: (token: string, group_token: string, message_id: number) =>
    request.postForm<PostGetGroupMessageStatusReturn>(API.GET_GROUP_MESSAGE_STATUS, {
      token,
      group_token,
      message_id
    }),
  removeGroupFromList: (token: string, group_token: string) =>
    request.postForm<ResponseType>(API.REMOVE_GROUP_FROM_LIST, { token, group_token }),
  canCreateGroup: (token: string) =>
    request.postForm<PostCanCreateGroupReturn>(API.CAN_CREATE_GROUP, { token }),
  getPinnedGroup: (token: string, group_token: string) =>
    request.postForm<PostGetPinnedGroupMessageReturn>(API.GET_PINNED_GROUP_MESSAGE, {
      token,
      group_token
    }),
  setPinGroupMessage: (token: string, message_id: number, group_token: string, pin: 0 | 1) =>
    request.postForm<ResponseType>(API.SET_PIN_GROUP_MESSAGE, {
      token,
      message_id,
      group_token,
      pin
    }),
  editGroupMessage: (data: PostEditGroupMessage) =>
    request.postForm<ResponseType>(API.EDIT_GROUP_MESSAGE, data),
  editMessage: (data: PostEditMessage) => request.postForm<ResponseType>(API.EDIT_MESSAGE, data),
  canSendMessage: (token: string, to_uid: number) =>
    request.postForm<PostCanSendMessageReturn>(API.CAN_SEND_MESSAGE, { token, to_uid })
};
