import { useAuth, useClerk } from '@clerk/nextjs';
import { observer } from 'mobx-react-lite';
import { usePathname } from 'next/navigation';
import React, { useState } from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import Button from '@/components/button/ReactAriaCompatButton';
import { ThumbsUpIcon } from '@/icons';
import { isLiked as getIsLiked } from '@/state/clipStore';
import { getClerkSignInRedirectProps, getCountString } from '@/utils/utils';

export type ClipLikeButtonProps = {
  clipId: string;
  showCount?: boolean;
  hideCountIfZero?: boolean;
  ref?: React.RefObject<any>;
  // additional click handler for logging metrics, etc for a logged in user
  onClick?: ({
    likeCount,
    isLiked,
  }: {
    likeCount: number;
    isLiked: boolean;
  }) => void;
  // this is used for things like appending anonymous user params to the redirect url
  clerkRedirectProps?:
    | (() => ReturnType<typeof getClerkSignInRedirectProps>)
    | ReturnType<typeof getClerkSignInRedirectProps>;
  // this is used for cases like the unauth song page opening a sign in modal instead of clerk
  onClickForAnonymousUserOverride?: () => void;
} & Omit<React.ComponentProps<typeof Button>, 'onClick'>;

export const ClipLikeButton = observer((props: ClipLikeButtonProps) => {
  const { isSignedIn } = useAuth();
  const clerk = useClerk();
  const pathname = usePathname();

  const {
    clipId,
    onClick,
    ref,
    showCount = true,
    clerkRedirectProps,
    hideCountIfZero = false,
    onClickForAnonymousUserOverride,
    ...restProps
  } = props;
  const { clips: clipStore } = useStores();

  const clip = clipStore.clipById[clipId];
  const isLiked = getIsLiked(clip);
  const likeCount = clip?.upvote_count || 0;
  const [currentUpvoteCount, setCurrentUpvoteCount] = useState(likeCount || 0);

  const handleLikeClick = () => {
    const newStatus = !getIsLiked(clip);

    const clerkRedirectProps =
      typeof props.clerkRedirectProps === 'function'
        ? props.clerkRedirectProps()
        : props.clerkRedirectProps || getClerkSignInRedirectProps(pathname);

    if (!isSignedIn) {
      if (onClickForAnonymousUserOverride) {
        onClickForAnonymousUserOverride();
      } else {
        clerk.openSignIn({
          withSignUp: true,
          ...clerkRedirectProps,
        });
      }
    } else {
      if (clipStore.isUpdatingClipReaction) {
        return;
      }
      if (onClick) {
        onClick({ likeCount: currentUpvoteCount, isLiked: newStatus });
      }
      clipStore.likeClip(clipId, newStatus);
      setCurrentUpvoteCount((prevCount: number | undefined) =>
        Math.max((prevCount || 0) + (newStatus ? 1 : -1), 0)
      );
    }
  };

  return (
    <Button
      {...(restProps as React.ButtonHTMLAttributes<HTMLButtonElement>)}
      ref={ref}
      icon={ThumbsUpIcon}
      active={isLiked}
      onClick={handleLikeClick}
    >
      {showCount ? getCountString(likeCount, hideCountIfZero) : null}
    </Button>
  );
});
