import { type FC, memo, useMemo } from 'react';
import { useQuery } from 'react-query';
import { useNavigate } from 'react-router-dom';

import { IconChartBar } from '@material-hu/icons/tabler';
import Box from '@material-hu/mui/Box';
import { cardActionAreaClasses } from '@material-hu/mui/CardActionArea';
import { cardContentClasses } from '@material-hu/mui/CardContent';
import IconButton from '@material-hu/mui/IconButton';
import Stack from '@material-hu/mui/Stack';
import { useTheme } from '@material-hu/mui/styles';
import Typography from '@material-hu/mui/Typography';

import Button from '@material-hu/components/design-system/Buttons/Button';
import HuCardContainer from '@material-hu/components/design-system/CardContainer';
import HuTooltip from '@material-hu/components/design-system/Tooltip';

import { useAuth } from 'src/contexts/JWTContext';
import useFeatureFlag from 'src/hooks/useFeatureFlag';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import usePermissions from 'src/hooks/usePermissions';
import { usePostAttachments } from 'src/hooks/usePostAttachments';
import { usePostReactions } from 'src/hooks/usePostReactions';
import { usePostViewers } from 'src/hooks/usePostViewers';
import EventPostComments from 'src/pages/dashboard/events/components/EventPostComments';
import EventPostMenu from 'src/pages/dashboard/events/components/EventPostMenu';
import PostComments from 'src/pages/dashboard/feed/components/PostComments';
import useCanViewPostInsights from 'src/pages/dashboard/feed/hooks/useCanViewPostInsights';
import { feedRoutes } from 'src/pages/dashboard/feed/routes';
import GroupPostComments from 'src/pages/dashboard/groups/components/GroupPostComments';
import { PostCardApprovalControls } from 'src/pages/dashboard/groups/components/PostCardApprovalControls';
import useCanViewGroupsInsights from 'src/pages/dashboard/groups/hooks/useCanViewGroupsInsights';
import { groupsKeys } from 'src/pages/dashboard/groups/queries';
import { groupsRoutes } from 'src/pages/dashboard/groups/routes';
import MarketplaceComments from 'src/pages/dashboard/marketplace/components/MarketplaceComments';
import MarketplacePostMenu from 'src/pages/dashboard/marketplace/components/MarketplacePostMenu';
import { getGroupDetails } from 'src/services/groups';
import { type Links } from 'src/types/actionLinks';
import { EventActions } from 'src/types/events';
import { FeatureFlags } from 'src/types/featureFlags';
import { ApprovalStatus, type GroupPost } from 'src/types/groups';
import { type Post } from 'src/types/posts';
import { StreamStatus } from 'src/types/stream';
import {
  canPerformAction,
  canPerformAnyAction,
  EDIT_ACTIONS,
  extractActionLinks,
  hasActionLinks,
} from 'src/utils/actionsLinks';
import {
  canApprovePosts,
  canComment,
  canEdit as canEditUtil,
  canReactContent,
  isPostApprovalRequested,
} from 'src/utils/feed';
import { useLokaliseTranslation as useTranslation } from 'src/utils/i18n';
import { getCurrentLocale } from 'src/utils/locale';
import {
  canComment as canCommentMarketplace,
  canDelete as canDeleteMarketplace,
  canEdit as canEditMarketplace,
  canReactContent as canReactMarketplace,
} from 'src/utils/marketplace';
import { UserPermissions } from 'src/utils/permissions';
import { formatPrice } from 'src/utils/prices';

import { PostProvider } from 'src/components/post/PostContext';
import { SharedPost } from 'src/components/post/SharedPost';

import { PostAction } from '../PostAction';
import PostCardContent from '../PostCardContent';
import { PostCardFeatures } from '../PostCardFeatures';
import PostCardHeader from '../PostCardHeader';
import PostCardReactions from '../PostCardReactions';

import { type UnifiedPostCardProps } from './types';

/**
 * A unified component for feed, group, and marketplace post cards.
 *
 * This component composes shared sub-components:
 * - PostCardHeader: User info, time, breadcrumb, action menu
 * - PostCardContent: Post body, streaming player, translation
 * - PostCardFeatures: Attachments, polls, link previews, gifs
 * - PostCardReactions: Reactions list
 * - Comments: Context-specific comments (PostComments, GroupPostComments, or MarketplaceComments)
 */
const UnifiedPostCard: FC<UnifiedPostCardProps> = memo(props => {
  const {
    context,
    post,
    isDetail = false,
    hideReactions = false,
    hideComments = false,
    hideTranslation = false,
    matchText = '',
    openProfileInNewTab = false,
    showExternalLink = false,
    postApprovalControls,
    onAddReaction = () => null,
    onRemoveReaction = () => null,
    hideAction = false,
    elementId,
    hideKeyUpdateHeader = false,
    abbreviateDate,
    hideFeatures = false,
    mediaMaxHeight,
    showSeeMoreToggle,
    onShowMore,
    onShowLess,
    onClick,
  } = props;

  const theme = useTheme();
  const navigate = useNavigate();
  const { t } = useTranslation(['marketplace', 'post']);
  const { user: loggedUser, permissions } = useAuth();
  const { hasAll: canCreateLiveStream } = usePermissions([
    UserPermissions.CREATE_LIVESTREAM,
  ]);
  const isMultipleEventOrganizersEnabled = useFeatureFlag(
    FeatureFlags.EVENTS_MULTIPLE_ORGANIZERS_ENABLED,
  );
  const isFeedContext = context === 'feed';
  const isGroupsContext = context === 'groups';
  const isMarketplaceContext = context === 'marketplace';
  const isEventsContext = context === 'events';

  const canViewFeedInsights = useCanViewPostInsights(post.user.id);
  const canViewGroupInsights = useCanViewGroupsInsights(
    isGroupsContext && 'isGroupAdmin' in props
      ? (props.isGroupAdmin ?? false)
      : false,
    post.user.id,
  );

  const {
    id,
    body,
    bodyHtml,
    bodyAttributes,
    user,
    commentCount,
    attachments,
    reactions,
    createdAt,
    updatedAt,
    lastComments,
    approvalStatus,
    stream,
    hasBeenSegmented,
    poll,
    languageCode,
    linkPreviews,
    isKeyUpdate,
    isExternal,
    commentsEnabled,
  } = post;

  // viewCount is only available on Post and GroupPost, not MarketplacePost
  const viewerCount =
    'viewCount' in post ? (post as Post | GroupPost).viewCount : undefined;

  // metadata is only available on Post and GroupPost (share-post feature)
  const shareMetadata =
    'metadata' in post ? (post as Post | GroupPost).metadata : null;

  const getGroupId = () => {
    if (isFeedContext) return post.group?.id;
    if (isGroupsContext) return Number(post.groupId);
    return undefined;
  };
  const groupId = getGroupId();
  const actionLinks = useMemo(
    () =>
      extractActionLinks(
        post as {
          _links?: Links;
        } & Record<string, unknown>,
      ),
    [post],
  );
  const hasBackendActions = hasActionLinks(actionLinks);

  const getEventId = () => {
    if (isEventsContext) return post.eventId;
    return undefined;
  };
  const eventId = getEventId();

  const { mediaList, fileList, audioList, gif } =
    usePostAttachments(attachments);

  const { handleAddReaction, handleRemoveReaction, getReactionUsers } =
    usePostReactions({
      context,
      postId: id,
      groupId,
      eventId,
      reactions,
      ...(isEventsContext
        ? {
            onAddReactionSuccess: onAddReaction,
            onRemoveReactionSuccess: onRemoveReaction,
          }
        : {
            onAddReactionOptimistic: onAddReaction,
            onRemoveReactionOptimistic: onRemoveReaction,
          }),
    });

  const { getViewers } = usePostViewers({
    context: isGroupsContext ? 'groups' : 'feed',
    postId: id,
    groupId,
  });

  // Permission checks
  const permissionChecks = useMemo(() => {
    if (isMarketplaceContext) {
      return {
        allowComments: canCommentMarketplace(permissions) && !hideComments,
        showReactions: canReactMarketplace(permissions) && !hideReactions,
        canEdit: !!loggedUser && canEditMarketplace(loggedUser.id, user.id),
        canDelete:
          !!loggedUser &&
          canDeleteMarketplace(loggedUser.id, user.id, permissions),
      };
    }

    if (isEventsContext) {
      const isPostCreator = loggedUser?.id === user.id;
      const isEventManager = props.isEventManager ?? false;
      const isEventCreator = props.isEventCreator ?? false;

      return {
        allowComments: canComment(permissions) && !hideComments,
        showReactions: canReactContent(permissions) && !hideReactions,
        canEdit: isMultipleEventOrganizersEnabled
          ? canPerformAction(post._links, EventActions.EDIT)
          : isPostCreator,
        canDelete: isMultipleEventOrganizersEnabled
          ? canPerformAction(post._links, EventActions.DELETE)
          : isEventManager || isEventCreator || isPostCreator,
      };
    }

    // Groups context: comments are allowed based on group membership, not feed permissions
    if (isGroupsContext) {
      const userCanInteract =
        (props.userIsMember ?? true) && !props.isGroupArchived;
      const isOwnPost = !!loggedUser && canEditUtil(loggedUser.id, user.id);
      const canEditByBackend =
        hasBackendActions && canPerformAnyAction(actionLinks, EDIT_ACTIONS);
      return {
        allowComments: userCanInteract && !hideComments,
        showReactions: userCanInteract && !hideReactions,
        canEdit: hasBackendActions
          ? canEditByBackend
          : isOwnPost &&
            (approvalStatus !== ApprovalStatus.PENDING || props.isGroupAdmin),
        canDelete: isOwnPost || props.isGroupAdmin,
      };
    }

    // Feed context
    const canEditByBackend =
      hasBackendActions && canPerformAnyAction(actionLinks, EDIT_ACTIONS);
    const canEditFallbackFeed =
      !!loggedUser &&
      canEditUtil(loggedUser.id, user.id) &&
      isFeedContext &&
      (canApprovePosts(permissions) ||
        !isPostApprovalRequested(permissions) ||
        approvalStatus !== ApprovalStatus.APPROVED);
    return {
      allowComments: canComment(permissions) && !hideComments,
      showReactions: canReactContent(permissions) && !hideReactions,
      canEdit: hasBackendActions ? canEditByBackend : canEditFallbackFeed,
      canDelete: undefined, // Handled separately for feed context
    };
  }, [
    permissions,
    loggedUser,
    user.id,
    isFeedContext,
    isGroupsContext,
    isMarketplaceContext,
    isEventsContext,
    approvalStatus,
    isMultipleEventOrganizersEnabled,
    hasBackendActions,
    actionLinks,
    hideComments,
    hideReactions,
  ]);

  const { allowComments, showReactions, canEdit, canDelete } = permissionChecks;

  // Determine if post is a group post shown in feed
  const feedGroup = isFeedContext ? (post as Post).group : null;
  const isGroupPostInFeed = isFeedContext && !!feedGroup;
  const loggedUserIsAdmin = (
    feedGroup as { loggedUserIsAdmin?: boolean } | null
  )?.loggedUserIsAdmin;
  const isFeedGroupAdmin =
    isGroupPostInFeed && typeof loggedUserIsAdmin === 'boolean'
      ? loggedUserIsAdmin
      : undefined;
  // Older feed payloads may omit `loggedUserIsAdmin`; in that case,
  // fall back to backend-controlled visibility via `viewCount`.
  const canShowGroupPostViewersInFeed =
    !isGroupPostInFeed || isFeedGroupAdmin !== false;
  const showViewers =
    viewerCount !== undefined &&
    viewerCount > 0 &&
    !isMarketplaceContext &&
    !isEventsContext &&
    canShowGroupPostViewersInFeed;

  // Grant video download for livestream posts
  const grantVideoDownload = Boolean(stream && canCreateLiveStream);

  const isLive = stream?.status === StreamStatus.LIVE;

  const { data: groupTitle } = useQuery(
    groupsKeys.detail(String(groupId)),
    () => getGroupDetails(String(groupId)),
    {
      select: response => response.data.title,
      enabled: isGroupsContext && !!post.groupId && props.showBreadcrumb,
    },
  );

  // Determine breadcrumb info (not applicable for marketplace or events)
  const breadcrumbInfo = useMemo(() => {
    if (isMarketplaceContext || isEventsContext) return undefined;

    if (isGroupPostInFeed && post.group) {
      return {
        title: post.group.title,
        link: groupsRoutes.detail(post.group.id),
        showMultiCompanyIcon: post.group.isMultiCompany,
      };
    }

    if (isGroupsContext && props.showBreadcrumb && post.groupId) {
      return {
        title: groupTitle ?? '',
        link: groupsRoutes.detail(post.groupId),
      };
    }
    return undefined;
  }, [
    isGroupsContext,
    isMarketplaceContext,
    isEventsContext,
    isGroupPostInFeed,
    groupTitle,
  ]);

  // External link URL (not applicable for marketplace or events)
  const externalLinkUrl = useMemo(() => {
    if (!showExternalLink || isMarketplaceContext || isEventsContext)
      return undefined;

    if (isGroupsContext) {
      return groupsRoutes.post.detail(post.groupId, id);
    }
    if (isGroupPostInFeed) {
      return groupsRoutes.post.detail(post.group?.id ?? 0, id);
    }
    if (isFeedContext) {
      return feedRoutes.post.detail(id);
    }

    // Should never happen, but in case we add a new context/case, we need to handle it
    return undefined;
  }, [
    isFeedContext,
    isGroupsContext,
    isEventsContext,
    isGroupPostInFeed,
    isMarketplaceContext,
    id,
  ]);

  // Render action component
  const renderAction = () => {
    if (hideAction) return null;

    if (isMarketplaceContext) {
      return (
        <MarketplacePostMenu
          id={id}
          isDetail={isDetail}
          showEdit={canEdit ?? false}
          showDelete={canDelete ?? false}
        />
      );
    }

    if (isEventsContext) {
      const isPostCreator = loggedUser?.id === user.id;
      const showEnableDisableComments = isPostCreator;
      const hasActions = canEdit || canDelete || showEnableDisableComments;
      if (!hasActions) return null;

      return (
        <EventPostMenu
          post={post}
          eventId={eventId ?? 0}
          showEdit={canEdit ?? false}
          showDelete={canDelete ?? false}
          showEnableDisableComments={showEnableDisableComments}
          onEdit={() => props.onEditPost?.(post)}
          onDelete={() => props.onDeletePost?.(post)}
        />
      );
    }

    if (isFeedContext) {
      return (
        <PostAction
          variant="feed"
          id={id}
          user={user}
          isPinned={props.isPinned ?? false}
          hidePinIcon={props.hidePinIcon}
          isKeyUpdate={isKeyUpdate}
          isPendingApproval={approvalStatus === ApprovalStatus.PENDING}
          isSegmented={hasBeenSegmented}
          poll={poll}
          commentsEnabled={commentsEnabled}
          externalLinkUrl={externalLinkUrl}
          canEdit={canEdit}
          actionLinks={actionLinks}
          isLive={isLive}
          isGroupPost={{
            value: isGroupPostInFeed,
            groupId: isGroupPostInFeed ? (post.group?.id ?? 0) : 0,
          }}
          originalPost={post as Post}
        />
      );
    }

    return (
      <PostAction
        variant="group"
        id={id}
        user={user}
        groupId={Number(post.groupId)}
        isPinned={props.isPinned ?? false}
        hidePinIcon={props.hidePinIcon}
        isKeyUpdate={isKeyUpdate}
        isPendingApproval={approvalStatus === ApprovalStatus.PENDING}
        isSegmented={hasBeenSegmented}
        poll={poll}
        externalLinkUrl={externalLinkUrl}
        commentsEnabled={commentsEnabled}
        actionLinks={actionLinks}
        isLive={isLive}
        originalPost={post as GroupPost}
      />
    );
  };

  const renderInsightsButton = () => {
    if (hideAction) return null;
    if (postApprovalControls) return null;

    if (isFeedContext && !isGroupPostInFeed && canViewFeedInsights) {
      return (
        <HuTooltip description={t('INSIGHTS')}>
          <IconButton
            onClick={() => navigate(feedRoutes.post.insights(id))}
            size="large"
          >
            <IconChartBar />
          </IconButton>
        </HuTooltip>
      );
    }

    if (isGroupsContext && canViewGroupInsights && groupId) {
      return (
        <HuTooltip description={t('INSIGHTS')}>
          <IconButton
            onClick={() => navigate(groupsRoutes.post.insights(groupId, id))}
            size="large"
          >
            <IconChartBar />
          </IconButton>
        </HuTooltip>
      );
    }

    return null;
  };

  const renderActionWithInsights = () => {
    const insightsButton = renderInsightsButton();
    const action = renderAction();

    if (!insightsButton && !action) return null;
    if (!insightsButton) return action;

    return (
      <Stack sx={{ flexDirection: 'row', alignItems: 'center' }}>
        {insightsButton}
        {action}
      </Stack>
    );
  };

  // Render comments component
  const renderComments = () => {
    if (!allowComments) return null;

    if (isMarketplaceContext) {
      return (
        <MarketplaceComments
          id={id}
          commentCount={commentCount}
          lastComments={lastComments}
          isDetail={isDetail}
        />
      );
    }

    if (isEventsContext) {
      return (
        <EventPostComments
          postId={id}
          commentCount={commentCount}
          lastComments={lastComments}
          commentsEnabled={commentsEnabled}
        />
      );
    }

    if (isFeedContext) {
      return (
        <PostComments
          id={id}
          commentCount={commentCount}
          lastComments={lastComments}
          user={user}
          segmentation={isMarketplaceContext ? [] : post.segmentation}
          hasBeenSegmented={hasBeenSegmented}
          commentsEnabled={commentsEnabled}
          viewerCount={showViewers ? viewerCount : undefined}
          getViewers={showViewers ? getViewers : undefined}
          viewersDisabled={reactionsDisabled}
        />
      );
    }

    return (
      <GroupPostComments
        id={id}
        commentCount={commentCount}
        lastComments={lastComments}
        commentsEnabled={commentsEnabled}
        viewerCount={showViewers ? viewerCount : undefined}
        getViewers={showViewers ? getViewers : undefined}
        viewersDisabled={reactionsDisabled}
      />
    );
  };

  // Determine if reactions should be disabled for groups
  const reactionsDisabled =
    isGroupsContext && (!props.userIsMember || props.isGroupArchived);

  const postHasText = (bodyHtml?.length ?? 0) > 0 || (body?.length ?? 0) > 0;

  // Render marketplace price and contact section
  const renderMarketplaceHeader = () => {
    if (!isMarketplaceContext) return null;

    // TODO: migrate to HuGo
    return (
      <Box
        sx={{
          px: 2,
          mt: 2,
          display: 'flex',
          flexDirection: 'row',
          justifyContent: 'space-between',
          alignItems: 'center',
        }}
      >
        <Typography
          color={theme => theme.palette.new.text.neutral.default}
          variant="globalM"
          fontWeight="fontWeightSemiBold"
        >
          {formatPrice(
            post.price ?? 0,
            post.currencySymbol ?? undefined,
            post.currencyCode ?? undefined,
            loggedUser ? getCurrentLocale(loggedUser) : undefined,
          )}
        </Typography>
        {props.showContact && props.onContact && (
          <Button
            variant="outlined"
            onClick={props.onContact}
            sx={{
              fontWeight: '500',
              fontSize: '13px',
              lineHeight: '22px',
              px: '10px',
              py: 0.5,
            }}
          >
            {t('marketplace:contact')}
          </Button>
        )}
      </Box>
    );
  };

  return (
    <PostProvider
      groupId={groupId}
      eventId={eventId}
    >
      <HuCardContainer
        id={elementId ?? `post-card-${id}`}
        padding={0}
        sx={{
          borderColor:
            context !== 'marketplace' && post?.hasBeenSegmented
              ? theme.palette.new.border.neutral.brand
              : theme.palette.new.border.neutral.default,
          [`& .${cardActionAreaClasses.root}`]: {
            alignItems: 'stretch',
            display: 'flex',
            height: '100%',
          },
          [`& .${cardContentClasses.root}`]: {
            display: 'flex',
            flexDirection: 'column',
            width: '100%',
          },
        }}
        fullWidth
        onClick={onClick}
      >
        <PostCardHeader
          user={user}
          publicationDatetime={post.publicationDatetime}
          updatedAt={updatedAt}
          createdAt={createdAt}
          approvalStatus={approvalStatus}
          isKeyUpdate={isKeyUpdate}
          isExternal={isExternal}
          openProfileInNewTab={openProfileInNewTab}
          stream={stream ?? undefined}
          isGroupPost={isGroupPostInFeed}
          breadcrumb={breadcrumbInfo}
          action={renderActionWithInsights()}
          hideKeyUpdateHeader={hideKeyUpdateHeader}
          abbreviateDate={abbreviateDate}
        />
        <Stack sx={{ pb: 2, px: 0, my: !postHasText ? 'auto' : undefined }}>
          {renderMarketplaceHeader()}
          <PostCardContent
            postId={id}
            body={body}
            bodyHtml={bodyHtml}
            bodyAttributes={bodyAttributes}
            languageCode={languageCode}
            stream={isEventsContext || !stream ? undefined : stream}
            hasAttachments={attachments?.length > 0}
            groupId={groupId}
            groupTitle={breadcrumbInfo?.title}
            reactions={reactions}
            onAddReaction={handleAddReaction}
            onRemoveReaction={handleRemoveReaction}
            getReactionUsers={getReactionUsers}
            user={user}
            updatedAt={updatedAt}
            createdAt={createdAt}
            commentCount={commentCount}
            commentsEnabled={commentsEnabled}
            matchText={matchText}
            hideTranslation={hideTranslation}
            showSeeMoreToggle={showSeeMoreToggle}
            onShowMore={onShowMore}
            onShowLess={onShowLess}
          />
          {shareMetadata && (
            <Stack sx={{ pt: postHasText ? 2 : 0 }}>
              <SharedPost metadata={shareMetadata} />
            </Stack>
          )}
          {!hideFeatures && (
            <Stack
              sx={{
                gap: 2,
                pt:
                  (postHasText && attachments.length > 0) || !!shareMetadata
                    ? 2
                    : 0,
              }}
            >
              <PostCardFeatures
                id={id}
                mediaList={mediaList}
                fileList={fileList}
                audioList={audioList}
                linkPreviews={linkPreviews}
                grantVideoDownload={grantVideoDownload}
                isDetail={isDetail}
                approvalStatus={
                  isMarketplaceContext ? undefined : approvalStatus
                }
                poll={poll}
                gif={isMarketplaceContext ? undefined : gif}
                userCanVote={
                  isFeedContext || (isGroupsContext && props.userIsMember)
                }
                parentElementId={elementId}
                mediaMaxHeight={mediaMaxHeight}
              />
              {showReactions && (
                <PostCardReactions
                  postId={id}
                  reactions={reactions}
                  handleAddReaction={handleAddReaction}
                  handleRemoveReaction={handleRemoveReaction}
                  getReactionUsers={getReactionUsers}
                  disabled={reactionsDisabled}
                />
              )}
              {renderComments()}
            </Stack>
          )}

          {postApprovalControls && (
            <PostCardApprovalControls
              postApprovalControls={postApprovalControls}
            />
          )}
        </Stack>
      </HuCardContainer>
    </PostProvider>
  );
});

UnifiedPostCard.displayName = 'UnifiedPostCard';

const UnifiedPostCardThemeProvider = (props: UnifiedPostCardProps) => {
  const HugoThemeProvider = useHuGoTheme();

  return (
    <HugoThemeProvider>
      <UnifiedPostCard {...props} />
    </HugoThemeProvider>
  );
};

export default UnifiedPostCardThemeProvider;
