export {};

export const enum InvitationTypeEnum {
  CommunityMemberInvite = 'communityMemberInvite',
  LivestreamInvite = 'livestreamInvite',
}

export const enum InvitationStatusEnum {
  Pending = 'pending',
  Approved = 'approved',
  Rejected = 'rejected',
  Cancelled = 'cancelled',
}

export const enum InvitationSortByEnum {
  FirstCreated = 'firstCreated',
  LastCreated = 'lastCreated',
}

declare global {
  namespace Amity {
    type InvitationType = InvitationTypeEnum;

    type InvitationStatus = InvitationStatusEnum;

    type InvitationTargetType = Extract<Amity.Domain, 'community'>;

    type InvitationTargetMap = {
      community: Amity.InternalCommunity;
    };

    type InvitationTarget<T extends InvitationTargetType> = InvitationTargetMap[T];

    type InvitationSortBy = InvitationSortByEnum;

    type InvitationDomain<T extends Amity.InvitationTargetType = Amity.InvitationTargetType> =
      T extends 'community' ? { communityId: string } : { communityId?: string };

    type RawInvitation = {
      _id: string;
      networkId: string;
      type: Amity.InvitationType;
      targetId: string;
      targetType: Amity.InvitationTargetType;
      userId: string;
      status: Amity.InvitationStatus;
      respondedAt: Amity.timestamp;
      createdBy: string;
      invitationId: string;
      invitedUserId: string;
      invitedUserInternalId: string;
      invitedUserPublicId: string;
      inviterUserId: string;
      inviterUserInternalId: string;
      inviterUserPublicId: string;
    } & Amity.Timestamps &
      Amity.InvitationDomain<Amity.InvitationTargetType>;

    type InternalInvitation = Omit<RawInvitation, 'createdBy'> & {
      createdById: string;
    };

    type Invitation = Omit<Amity.InternalInvitation, 'createdBy'> &
      Amity.InvitationLinkedObject & {
        user?: Amity.User;
        createdById: string;
        createdBy?: Amity.User;
        target?: Amity.InvitationTarget<Amity.InvitationTargetType>;
      };

    type QueryInvitations = {
      targetId: string;
      statuses?: string[];
      token?: Amity.Token;
      type: Amity.InvitationType;
      sortBy?: Amity.InvitationSortBy;
      limit?: Amity.PageLimit['limit'];
      targetType: Amity.InvitationTargetType;
    };

    type InvitationLiveCollection = Amity.LiveCollectionParams<Omit<QueryInvitations, 'limit'>>;

    type InvitationLiveCollectionCache = Amity.LiveCollectionCache<
      Amity.InternalInvitation['_id'],
      Pick<QueryInvitations, 'limit'>
    >;

    type QueryMyInvitations = {
      targetId?: string;
      token?: Amity.Token;
      type?: Amity.InvitationType;
      sortBy?: Amity.InvitationSortBy;
      limit?: Amity.PageLimit['limit'];
      statuses?: InvitationStatusEnum[];
      targetType?: Amity.InvitationTargetType;
    };

    type MyInvitationsLiveCollection = Amity.LiveCollectionParams<
      Omit<QueryMyInvitations, 'limit'>
    >;

    type MyInvitationsLiveCollectionCache = Amity.LiveCollectionCache<
      Amity.InternalInvitation['_id'],
      Pick<QueryMyInvitations, 'limit'>
    >;

    type InvitationLinkedObject = {
      accept: () => Promise<void>;
      reject: () => Promise<void>;
    };

    type CreateInvitations = {
      type: Amity.InvitationType;
      targetType: Amity.InvitationTargetType;
      targetId: string;
      userIds: string[];
    };
  }
}
