import { FC, createContext, useContext } from 'react';

import { useAuth } from 'src/contexts/JWTContext';
import {
  GroupPublicationPolicies,
  GroupMemberRoles,
  GroupPrivacyPolicies,
  Group,
  GroupApprovalPolicies,
  GroupMemberSource,
} from 'src/types/groups';
import { getUserGroupRoles } from 'src/utils/groups';

export type GroupMemberContextValue = {
  userIsMember: boolean;
  userRole: GroupMemberRoles | null;
  userCanPost: boolean;
  isGroupAdmin: boolean;
  userCanSeePosts: boolean;
  isClosedGroup: boolean;
  postsNeedApproval: boolean;
  isGroupArchived: boolean;
  userMembershipSource: GroupMemberSource | null;
  userCanLeave: boolean;
};

const GroupMemberContext = createContext<GroupMemberContextValue>({
  userIsMember: false,
  userRole: null,
  userCanPost: false,
  isGroupAdmin: false,
  userCanSeePosts: false,
  isClosedGroup: false,
  postsNeedApproval: false,
  isGroupArchived: false,
  userMembershipSource: null,
  userCanLeave: false,
});

type GroupMemberProvider = Pick<
  Group,
  | 'members'
  | 'publicationPolicy'
  | 'privacyPolicy'
  | 'approvalPolicy'
  | 'isArchived'
>;

export const GroupMemberProvider: FC<
  React.PropsWithChildren<GroupMemberProvider>
> = props => {
  const {
    children,
    members,
    publicationPolicy,
    privacyPolicy,
    approvalPolicy,
    isArchived,
  } = props;

  const { user } = useAuth();
  const { userIsMember, userRole, isGroupAdmin } = getUserGroupRoles(members);

  // Find current user's membership info
  const currentUserMember =
    user && members && members.length > 0
      ? members.find(member => member.userId === user.id)
      : null;

  const userMembershipSource = currentUserMember?.source ?? null;
  const userCanLeave = currentUserMember?.userCanLeave ?? false;

  const fulfilPostingPolicy =
    publicationPolicy === GroupPublicationPolicies.OPEN || isGroupAdmin;

  const userCanPost = userIsMember && fulfilPostingPolicy && !isArchived;

  const userCanSeePosts =
    userIsMember || privacyPolicy === GroupPrivacyPolicies.OPEN;

  const isClosedGroup = privacyPolicy === GroupPrivacyPolicies.CLOSE;
  const postsNeedApproval =
    approvalPolicy === GroupApprovalPolicies.ONLY_ADMINS;
  const isGroupArchived = isArchived || false;

  return (
    <GroupMemberContext.Provider
      value={{
        userIsMember,
        userRole,
        userCanPost,
        isGroupAdmin,
        userCanSeePosts,
        isClosedGroup,
        postsNeedApproval,
        isGroupArchived,
        userMembershipSource,
        userCanLeave,
      }}
    >
      {children}
    </GroupMemberContext.Provider>
  );
};

export const useGroupMember = () => useContext(GroupMemberContext);

export const GroupMemberConsumer = GroupMemberContext.Consumer;

export default GroupMemberContext;
