import {create} from 'zustand';
import {useShallow} from 'zustand/react/shallow';
import {Membership} from '@modules/chats/interfaces';
import {getNumMembers, getUserIdsFromChannel} from '@modules/chats/db';
import {getShortGroupMemberships} from '@modules/chats/db/services/groupMembershipService';
import {sentryLogs} from '@shared/utils';

interface GroupInfo {
  totalMembers: number;
  shortGroupMembers: Membership[];
  isUserAdmin: boolean;
}

interface VisibleChatStore {
  id: Nullable<string>;
  isChannel: boolean;
  groupInfo: GroupInfo | null;
  members: Nullable<Set<string>>;
  setVisibleChatId: (id: string) => void;
  setIsChannel: (isChannel: boolean) => void;
  getGroupInfo: (channel: string) => void;
  clear: () => void;
  addMembers: (members: string[]) => void;
  removeMembers: (members: string[]) => void;
}

export const visibleChatStore = create<VisibleChatStore>(set => ({
  id: null,
  isChannel: false,
  groupInfo: null,
  members: null,
  setVisibleChatId: (id: string) => set({id}),
  setIsChannel: isChannel =>
    set(state => (state.isChannel === isChannel ? state : {isChannel})),
  getGroupInfo: async (id: string) => {
    try {
      const [totalMembers, shortGroupMembers] = await Promise.all([
        getNumMembers(id),
        getShortGroupMemberships(id),
      ]);
      set({
        groupInfo: {
          totalMembers,
          shortGroupMembers: shortGroupMembers.memberships,
          isUserAdmin: shortGroupMembers.isUserAdmin,
        },
      });
      /**
       * Get member list after other promises since this query could take a while
       * and we don't want to block other info
       */
      const members = await getUserIdsFromChannel(id);
      set({members: new Set(members.map(member => member.toString()))});
    } catch (error) {
      sentryLogs.error({
        message: 'Error getting group info',
        module: 'CHATS',
        component: 'visibleChatStore',
        error,
      });
    }
  },
  clear: () => {
    set({id: null, isChannel: false, groupInfo: null, members: null});
  },
  addMembers: (newMembers: string[]) =>
    set(state => ({
      members: new Set([...(state.members ?? []), ...newMembers]),
    })),
  removeMembers: (removedMembers: string[]) =>
    set(state => ({
      members: state.members
        ? new Set([...state.members].filter(m => !removedMembers.includes(m)))
        : null,
    })),
}));

export const updateVisibleChatId = (payload: string) => {
  visibleChatStore.getState().setVisibleChatId(payload);
};

export const updateVisibleChatIsChannel = (payload: boolean) => {
  visibleChatStore.getState().setIsChannel(payload);
};

export const clearVisibleChat = () => {
  visibleChatStore.getState().clear();
};

export const useVisibleChatGroupInfo = () =>
  visibleChatStore(useShallow(state => state.groupInfo));

export const useIsUserAdminOfVisibleChat = () =>
  visibleChatStore(useShallow(state => state.groupInfo?.isUserAdmin || false));

export const getVisibleChatId = () => {
  return visibleChatStore.getState().id;
};

export const useVisibleChatId = () => visibleChatStore(state => state.id);

export const useVisibleChatMembers = () =>
  visibleChatStore(useShallow(state => state.members));
