import { type RefObject } from 'react';

import { type SxProps, type Theme } from '@material-hu/mui/styles';

import {
  type Comment as CommentType,
  type PostCommentPayload,
} from 'src/types/comments';
import { type CursorPagination } from 'src/types/services';
import { type TaggedUser } from 'src/types/user';

import { type GetChildCommentsQueryConfigReturn } from './commentConfigs';

// ============================================================================
// CORE TYPES
// ============================================================================

// Type for comments response - can be either array or cursor paginated
export type CommentsResponse = CommentType[] | CursorPagination<CommentType[]>;

export type ReplyState = {
  id?: number | null;
  user?: CommentType['user'];
} | null;

export type CommentPermissions = {
  canDelete: boolean;
  canReact: boolean;
  canEdit: boolean;
  canReply: boolean;
};

// ============================================================================
// MUTATION TYPES
// ============================================================================

export type CommentMutation = {
  mutate: (data: [PostCommentPayload, TaggedUser[]]) => void;
  mutateAsync: (data: [PostCommentPayload, TaggedUser[]]) => Promise<unknown>;
  isLoading: boolean;
  isSuccess: boolean;
};

export type ReplyMutation = {
  mutate: (data: PostCommentPayload) => void;
  mutateAsync: (data: PostCommentPayload) => Promise<unknown>;
  isLoading: boolean;
};

// ============================================================================
// HANDLER TYPES
// ============================================================================

export type GetCommentToScrollRef = (
  commentId: number,
  parentId: string | null,
  ref: RefObject<HTMLElement>,
) => RefObject<HTMLElement> | null;

export type CommentHandlers = {
  handleBlur: () => void;
  handleClickComment: () => void;
  handleDeleteSuccess: (commentId: number, parentId: number | null) => void;
  handleEditSuccess: (comment: CommentType) => void;
  handleAddReactionSuccess: (
    commentId: number,
    parentId: number | null,
    emoji: string,
    unified: string,
  ) => void;
  handleRemoveReactionSuccess: (
    commentId: number,
    parentId: number | null,
    emoji: string,
  ) => void;
  handleReply: (replyId: number | null) => void;
  handleReplyChild: (
    _replyId: number,
    parentId: number | null,
    user: CommentType['user'],
  ) => void;
  handleReplyBlur: () => void;
  handleDeleteUserReply: () => void;
  showLoadMoreComments: (
    data: unknown,
    lastComments: CommentType[],
    commentCount: number,
  ) => boolean;
  handleScrollToComment: (
    commentToScrollToRef: RefObject<HTMLElement>,
    comments: CommentType[],
  ) => void;
  getChildCommentsQueryConfig: (
    comment: CommentType,
  ) => GetChildCommentsQueryConfigReturn;
  handleReplyComment: (formData: PostCommentPayload) => Promise<void>;
};

// ============================================================================
// BASE PROPS - Shared across different component types
// ============================================================================

type ReactionHandlers = {
  onDelete: (commentId: number, parentId: number | null) => void;
  onRemoveReaction: (
    commentId: number,
    parentId: number | null,
    emoji: string,
  ) => void;
  onAddReaction: (
    commentId: number,
    parentId: number | null,
    emoji: string,
    unified: string,
  ) => void;
};

type BaseItemProps = {
  postId: number;
  maxAttachmentsBytes: number;
};

type ReplyHandlingProps = {
  reply: ReplyState;
  replyCommentMutation?: ReplyMutation;
  isReplyFocused?: boolean;
  handleReplyBlur?: () => void;
  handleDeleteUserReply?: () => void;
};

type PermissionProps = {
  canManageComments: boolean;
  canReact: boolean;
};

type ScrollProps = {
  parentIdParams?: string | null;
  commentToScrollToRef?: RefObject<HTMLElement>;
  getCommentToScrollRef?: GetCommentToScrollRef;
};

// ============================================================================
// COMPONENT CUSTOMIZATION TYPES
// ============================================================================

export type BaseCommentComponentProps = BaseItemProps &
  ReactionHandlers & {
    comment: CommentType;
  };

export type BaseChildCommentListProps = BaseItemProps &
  ReactionHandlers & {
    childrenNumber: number;
  };

// ============================================================================
// COMMENT ITEM PROPS
// ============================================================================

type CommentItemBaseProps = BaseItemProps &
  ReplyHandlingProps &
  PermissionProps &
  ScrollProps & {
    handlers: CommentHandlers;
  };

export type GroupVariantProps = {
  context: 'groups';
  isGroupArchived?: boolean;
  userIsMember?: boolean;
  isGroupAdmin?: boolean;
  canManageComments?: never;
  canReact?: never;
  parentIdParams?: never;
  commentToScrollToRef?: never;
  getCommentToScrollRef?: never;
};

export type StandardVariantProps = {
  context: 'feed' | 'articles' | 'acknowledgements' | 'marketplace' | 'events';
  isGroupArchived?: never;
  userIsMember?: never;
  isGroupAdmin?: never;
  canManageComments: boolean;
  canReact: boolean;
};

export type CommentItemProps = Omit<
  CommentItemBaseProps,
  keyof PermissionProps | 'context'
> & {
  comment: CommentType;
} & (GroupVariantProps | StandardVariantProps);

// ============================================================================
// COMMENT LIST PROPS
// ============================================================================

type BaseListProps = {
  comments: CommentType[];
};

export type CommentItemBasePropsWithoutComment = Omit<
  CommentItemBaseProps,
  keyof PermissionProps | 'context'
>;

export type StandardCommentListProps = BaseListProps &
  CommentItemBasePropsWithoutComment &
  StandardVariantProps;

export type GroupCommentListProps = BaseListProps &
  CommentItemBasePropsWithoutComment &
  GroupVariantProps;

// ============================================================================
// COMMENTS SYSTEM COMPONENT PROPS
// ============================================================================

type CommentsSystemBaseProps = {
  postId: number;
  commentCount: number;
  lastComments: CommentType[];
  isDetail?: boolean;
  commentsEnabled?: boolean;

  // UI customization
  containerSx?: SxProps<Theme>;

  // Error handling
  onError?: (error: Error) => void;
  commentToScrollToRef?: RefObject<HTMLElement>;

  // Viewer props (optional)
  viewerCount?: number;
  getViewers?: (params?: {
    limit?: number;
    cursor?: string;
    search?: string;
  }) => Promise<any>;
  viewersDisabled?: boolean;
};

export type CommentsSystemComponentProps =
  | (CommentsSystemBaseProps & {
      context: 'feed';
      FeedProps: FeedCommentsProps;
      GroupsProps?: undefined;
      ArticlesProps?: undefined;
      EventsProps?: undefined;
    })
  | (CommentsSystemBaseProps & {
      context: 'groups';
      FeedProps?: undefined;
      GroupsProps: GroupsCommentsProps;
      ArticlesProps?: undefined;
      EventsProps?: undefined;
    })
  | (CommentsSystemBaseProps & {
      context: 'articles';
      FeedProps?: undefined;
      GroupsProps?: undefined;
      ArticlesProps: ArticlesCommentsProps;
      EventsProps?: undefined;
    })
  | (CommentsSystemBaseProps & {
      context: 'acknowledgements' | 'marketplace';
      FeedProps?: undefined;
      GroupsProps?: undefined;
      ArticlesProps?: undefined;
      EventsProps?: undefined;
    })
  | (CommentsSystemBaseProps & {
      context: 'events';
      FeedProps?: undefined;
      GroupsProps?: undefined;
      ArticlesProps?: undefined;
      EventsProps: EventsCommentsProps;
    });

// Feed-specific props
type FeedCommentsProps = {
  parentIdParams?: string | null;
  // Segmentation (optional)
  showSegmentation?: boolean;
  segmentation?: unknown;
  hasBeenSegmented?: boolean;
  amountOfUsersReach?: number;
  onOpenSegmentationDrawer?: () => void;
  segmentationDrawer?: React.ReactNode;
};

// Groups-specific props
type GroupsCommentsProps = {
  groupId: string;
  parentIdParams?: string | null;
  userIsMember?: boolean;
  isGroupArchived?: boolean;
  isGroupAdmin?: boolean;
};

// Articles-specific props
type ArticlesCommentsProps = {
  parentIdParams?: string | null;
  commentsRef?: RefObject<HTMLElement>;
};

// Events-specific props
type EventsCommentsProps = {
  parentIdParams?: string | null;
};
