import React, { useCallback, useMemo, useState } from 'react';
import {
  StyleSheet,
  TextStyle,
  TouchableOpacity,
  View,
  ViewStyle,
} from 'react-native';
import { userProfile } from '@livelike/javascript';
import {
  useStyles,
  useReactionSpace,
  useUserReactions,
  useUserReactionActions,
  useAnalytics,
} from '../../hooks';
import { ComponentStyleProp, LLComponentStyleFn } from '../../types';
import { LLReactionPicker, LLReactionPickerProps } from './LLReactionPicker';
import {
  LLUserReactionCountDetail,
  LLUserReactionCountDetailProps,
} from './LLUserReactionCountDetail';
import { LLText } from '../LLText';

export type LLUserReactionCountsStyles = {
  reactionCountsContainer: ViewStyle;
  moreReactionsView: ViewStyle;
  moreReactionsText: TextStyle;
};

export type LLUserReactionCountsProps =
  ComponentStyleProp<LLUserReactionCountsStyles> & {
    targetGroupId: string;
    targetId: string;
    showReactionPicker?: boolean;
    reactionsLimit?: number;
    onReactionItemPress?: () => void;
    UserReactionCountDetailComponent?: typeof LLUserReactionCountDetail;
    UserReactionCountDetailComponentStyles?: LLUserReactionCountDetailProps['styles'];
    MessageReactionPickerComponent?: typeof LLReactionPicker;
    MessageReactionPickerComponentStyles?: LLReactionPickerProps['styles'];
  };

const DEFAULT_REACTIONS_LIMIT = 4;
const DUMMY_USER_REACTION_ID = 'DUMMY_USER_REACTION_ID';

export function LLUserReactionCounts({
  targetGroupId,
  targetId,
  showReactionPicker,
  onReactionItemPress,
  styles: stylesProp,
  MessageReactionPickerComponentStyles,
  UserReactionCountDetailComponentStyles,
  reactionsLimit = DEFAULT_REACTIONS_LIMIT,
  UserReactionCountDetailComponent = LLUserReactionCountDetail,
  MessageReactionPickerComponent = LLReactionPicker,
}: LLUserReactionCountsProps) {
  const [showAllReactions, setShowAllReactions] = useState(false);
  const { reactionSpace } = useReactionSpace({
    targetGroupId,
  });
  const reactionSpaceId = reactionSpace?.id;
  const { userReactions } = useUserReactions({
    reactionSpaceId,
    targetId,
  });
  const userReactionCountStyles = useStyles({
    componentStylesFn: getRUserReactionCountStyles,
    stylesProp,
  });
  const { addReaction, removeReaction } = useUserReactionActions({
    targetGroupId,
    targetId,
  });
  const { trackEvent } = useAnalytics();

  const onReactionItemPressHandler = useCallback(
    async (reactionId: string) => {
      const selfReactionId =
        userReactions?.[reactionId]?.self_reacted_user_reaction_id;
      const actionArgs = {
        reactionSpaceId: reactionSpace?.id,
        userReaction: {
          target_id: targetId,
          reaction_id: reactionId,
          reacted_by_id: userProfile.id,
          id: DUMMY_USER_REACTION_ID,
        },
        profileId: userProfile.id,
      };
      if (selfReactionId) {
        removeReaction(actionArgs, selfReactionId);
      } else {
        addReaction(actionArgs);
      }
      onReactionItemPress?.();
    },
    [userReactions, reactionSpaceId, targetId, addReaction, removeReaction]
  );
  const onReactionPanelOpen = useCallback(() => {
    trackEvent('Reaction Panel Opened', {
      targetId,
      targetGroupId,
    });
  }, []);
  const onReactionPanelClose = useCallback(() => {
    trackEvent('Reaction Panel Closed', {
      targetId,
      targetGroupId,
    });
  }, [targetId, targetGroupId, trackEvent]);
  const userReactionValues = useMemo(
    () => Object.values(userReactions),
    [userReactions]
  );

  const reactionsRenderer = useMemo(
    () => (limit?: number) =>
      userReactionValues.map(
        (reaction, index) =>
          (!limit || index < limit) &&
          reaction.count > 0 && (
            <UserReactionCountDetailComponent
              reaction={reaction}
              onPress={onReactionItemPressHandler}
              key={reaction.reaction_id}
              styles={UserReactionCountDetailComponentStyles}
            />
          )
      ),
    [userReactions]
  );

  const onShowAllReactionCounts = useCallback(() => {
    setShowAllReactions(true);
  }, [setShowAllReactions]);

  return (
    <>
      <View style={userReactionCountStyles.reactionCountsContainer}>
        {reactionsRenderer(
          showAllReactions ? userReactionValues.length : reactionsLimit
        )}
        {!showAllReactions && userReactionValues.length > reactionsLimit && (
          <TouchableOpacity
            onPress={onShowAllReactionCounts}
            accessibilityLabel="More reactions"
            style={userReactionCountStyles.moreReactionsView}
          >
            <LLText style={userReactionCountStyles.moreReactionsText}>
              {`+${userReactionValues.length - reactionsLimit} more`}
            </LLText>
          </TouchableOpacity>
        )}
      </View>
      {showReactionPicker && (
        <MessageReactionPickerComponent
          visible={showReactionPicker}
          onReactionPanelOpen={onReactionPanelOpen}
          onReactionPanelClose={onReactionPanelClose}
          reactionSpaceId={reactionSpace?.id}
          onPress={onReactionItemPressHandler}
          styles={MessageReactionPickerComponentStyles}
        />
      )}
    </>
  );
}

const getRUserReactionCountStyles: LLComponentStyleFn<
  LLUserReactionCountsStyles
> = ({ theme }) =>
  StyleSheet.create({
    reactionCountsContainer: {
      flexDirection: 'row',
      flexWrap: 'wrap',
      marginHorizontal: 3,
      flex: 1,
    },
    moreReactionsView: {
      flexDirection: 'row',
      alignItems: 'center',
      backgroundColor: theme.popoverBackground,
      marginHorizontal: 3,
      marginBottom: 4,
      paddingHorizontal: 5,
      paddingVertical: 2,
      borderRadius: 4,
    },
    moreReactionsText: {
      color: theme.text,
      fontSize: 11,
      lineHeight: 22,
      fontWeight: 'bold',
    },
  });
