import { type Attachment } from 'src/types/attachments';
import { type Comment } from 'src/types/comments';
import { type LinkPreviewResponse } from 'src/types/previewLink';
import { type Reaction } from 'src/types/reaction';
import { type ItemSegmentation } from 'src/types/segmentation';
import { type CursorPagination, type Pagination } from 'src/types/services';
import { type TaggedUser, type User } from 'src/types/user';

import { type Links } from './actionLinks';
import { type PostState } from './feed';
import { type ApprovalStatus, type Group } from './groups';
import { type LiveStream } from './stream';

export enum InsightsTypes {
  VIEWERS = 'viewers',
  REACTIONS = 'reactors',
  COMMENTS = 'commenters',
}

export type Voter = {
  id: number;
  updatedAt: string;
  createdAt: string;
  firstName: string;
  lastName: string;
  profilePicture: string;
  email: string;
  isExternal: boolean;
};

export type PollOption = {
  id: number;
  option: string;
  position: number;
  answerCount: number;
  isLoggedUserAnswer: boolean;
  voters?: Array<Voter>;
};

export type Poll = {
  id: number;
  totalAnswerCount: number;
  pollOptions: PollOption[];
  hasBeenAnswered: boolean;
  pollConfiguration?: {
    isAnonymous: boolean;
    endsAt?: string | null;
  };
};

export type PostSegmentation = {
  id: number;
  item: ItemSegmentation;
};

export type SharePostIdMetadata = {
  SHARE_POST_ID: { id: number; link: string };
};

export type ShareGroupPostIdMetadata = {
  SHARE_GROUP_POST_ID: { id: number; groupId: number; link: string };
};

export type ShareMetadata = SharePostIdMetadata | ShareGroupPostIdMetadata;

export type SharePostIdMetadataInput = {
  SHARE_POST_ID: { id: number };
};

export type ShareGroupPostIdMetadataInput = {
  SHARE_GROUP_POST_ID: { id: number; groupId: number };
};

export type ShareMetadataInput =
  | SharePostIdMetadataInput
  | ShareGroupPostIdMetadataInput;

export enum PostType {
  FeedType = 'feed',
  GroupType = 'group',
  MarketplaceType = 'marketplace',
}

export enum PostRequestActionType {
  CREATION = 'CREATION',
  EDITION = 'EDITION',
}

export type PostRequestContent = {
  id: string;
  postId: number;
  isCurrentContent: boolean;
  instanceId: number;
  body: string | null;
  bodyHtml: string | null;
  bodyAttributes: TaggedUser[];
  taggedUserIds: number[];
  linkPreviews: Record<string, LinkPreviewResponse> | null;
  contentPublicationDatetime: string | null;
  createdAt: string;
  updatedAt: string;
  /** Proposed attachments for an edition request (when returned by the API). */
  attachments?: Attachment[] | null;
  poll?: Poll | null;
};

export type Post<T extends Group | DraftGroup = Group> = {
  id: number;
  body: string;
  bodyHtml?: string;
  bodyAttributes?: TaggedUser[];
  taggedUserIds: number[];
  user: Pick<User, 'firstName' | 'id' | 'lastName' | 'profilePicture'>;
  updatedAt: string;
  createdAt: string;
  poll: Poll | null;
  commentCount: number;
  viewCount?: number;
  attachments: Attachment[];
  reactions: Reaction[];
  segmentation: PostSegmentation[];
  hasBeenSegmented: boolean;
  linkPreviews: Record<string, LinkPreviewResponse>;
  publicationDatetime: string;
  state: PostState;
  lastComments: Comment[];
  commentsEnabled: boolean;
  viewed: boolean;
  stream?: LiveStream;
  languageCode: string | null;
  approvalStatus: ApprovalStatus;
  group: T | null;
  type: PostType.FeedType;
  externalId: string | null;
  isKeyUpdate: boolean;
  sendNotification: boolean;
  isExternal: boolean;
  metadata: ShareMetadata | null;
  _links?: Links;
};

export type AudienceUser = User & {
  firstInteraction?: string;
  lastInteraction: string;
};

export type PostViewer = {
  seenAt: string;
  viewer: {
    id: number;
    email: string;
    firstName: string;
    lastName: string;
    profilePicture: string | null;
    instanceId: number;
    isExternal: boolean;
  };
};

// Data
export type PostData = {
  body: string;
  bodyHtml?: string;
  bodyAttributes?: TaggedUser[];
  attachments: Attachment[];
  poll?: {
    pollOptions: string[];
    pollConfiguration?: {
      isAnonymous: boolean;
      endsAt?: string | null;
    };
  };
  sendNotification: boolean;
  publicationDatetime?: string | null;
  segmentationItemIds: number[];
  taggedUserIds?: number[];
  streamId?: string;
  commentsEnabled?: boolean;
  metadata?: ShareMetadataInput;
  linkPreviews?: Record<string, LinkPreviewResponse | null>;
};

// Response
export type InsightsSummaryResponse = {
  commentCount: number;
  reactionCount: number;
  viewerCount: number;
};

export type InsightsAudienceResponse = Pagination<AudienceUser[]>;

export type InsightsReportResponse = BlobPart;

// Sockets
export type PostReactionSocket = {
  emoji: string;
  unified: string;
  userId: number;
  postId: number;
};

export type PostCommentReactionSocket = {
  emoji: string;
  unified: string;
  userId: number;
  parentId: number;
  commentId: number;
  postId: number;
};

export type PostCommentCreatedSocket = Comment & {
  postId: number;
};

export type PostCommentDeletedSocket = {
  commentId: number;
  parentId: number;
  postId: number;
};

export type PostStreamSocket = {
  liveStreamId: number;
  postId: number;
  recordingUrl?: string;
  captionsEnabled?: boolean;
};

export type GroupPostStreamSocket = {
  groupId: number;
  postId: number;
  liveStreamId: number;
  recordingUrl?: string;
  captionUrl?: string;
  captionsEnabled?: boolean;
};

export type PostHlsStreamSocket = {
  hlsUrl: string;
  postId: number;
  liveStreamId: string;
};

export type GroupPostHlsStreamSocket = {
  hlsUrl: string;
  postId: number;
  groupId: number;
  liveStreamId: string;
};

export type EventPostStreamSocket = {
  eventId: number;
  postId: number;
  liveStreamId: number;
  recordingUrl?: string;
  captionUrl?: string;
  captionsEnabled?: boolean;
};

export type EventPostHlsStreamSocket = {
  hlsUrl: string;
  postId: number;
  eventId: number;
  liveStreamId: string;
};

export type DraftPermissionUser = Pick<
  User,
  'createdAt' | 'email' | 'firstName' | 'id' | 'lastName' | 'profilePicture'
>;

export type DraftPermission = {
  createdAt: string;
  id: number;
  userFrom: DraftPermissionUser;
  userFromId: number;
  userTo: DraftPermissionUser;
  userToId: number;
};

export type DraftPermissionResponse = CursorPagination<DraftPermission[]>;

export type DraftRequest = {
  approvalStatus: ApprovalStatus;
  createdAt: string;
  draftPermission: DraftPermission;
  draftPermissionId: number;
  id: number;
  isScheduled: boolean;
  post: Post<DraftGroup>;
  postId: number;
  state: DraftStatus;
  userFromId: number;
  userToId: number;
};

export type DraftRequestsResponse = CursorPagination<DraftRequest[]>;

export enum DraftStatus {
  IN_PROGRESS = 'IN_PROGRESS',
  PENDING = 'PENDING',
  OVERDUE = 'OVERDUE',
  APPROVED = 'APPROVED',
  REJECTED = 'REJECTED',
}

export const DraftStatusGeneral = {
  [DraftStatus.IN_PROGRESS]: DraftStatus.IN_PROGRESS,
  [DraftStatus.APPROVED]: DraftStatus.APPROVED,
};

export const DraftInProgressFilters = {
  [DraftStatus.IN_PROGRESS]: DraftStatus.IN_PROGRESS,
  [DraftStatus.PENDING]: DraftStatus.PENDING,
  [DraftStatus.OVERDUE]: DraftStatus.OVERDUE,
};

export enum UserAsValues {
  DRAFTER = 'DRAFTER',
  FINAL_AUTHOR = 'FINAL_AUTHOR',
}

export type DraftGroup = Pick<
  Group,
  | 'id'
  | 'title'
  | 'membersCount'
  | 'approvalPolicy'
  | 'createdAt'
  | 'description'
  | 'instanceId'
  | 'privacyPolicy'
  | 'publicationPolicy'
> & { updatedAt: string; loggedUserIsAdmin: boolean; icon: string };

export type DraftGroupsResponse = CursorPagination<DraftGroup[]>;
