import clsx from 'clsx';
import { observer } from 'mobx-react-lite';
import { useCallback, useEffect, useRef, useState } from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import { RotateReverseIcon } from '@/icons';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { TagSuggestionContexts } from '@/state/createV2Store';
import { CREATE_VERSION } from '@/utils/constants';

import { SuggestedStyle } from './SuggestedStyle';

export enum SuggestedStylesVariants {
  OneLine = 'one_line',
  TwoLine = 'two_line',
}

type Props = {
  isShown: boolean;
  icon?: React.FC;
  allowRefresh?: boolean;
  onClickStyle?: (style: string) => void;
  variant?: SuggestedStylesVariants;
  context: TagSuggestionContexts;
};

export const SuggestedStyles = observer(
  ({
    isShown,
    icon,
    onClickStyle,
    allowRefresh = true,
    context,
    variant = SuggestedStylesVariants.TwoLine,
  }: Props) => {
    const { createV2 } = useStores();
    const scrollContainerRef = useRef<any>(null);
    const [needsCorrectivePadding, setNeedsCorrectivePadding] =
      useState<boolean>(false);

    useEffect(() => {
      setNeedsCorrectivePadding(
        !!scrollContainerRef.current &&
          (scrollContainerRef.current?.offsetHeight || 0) -
            (scrollContainerRef.current?.clientHeight || 0) ===
            0
      );
    }, [
      scrollContainerRef.current,
      scrollContainerRef.current?.offsetHeight,
      scrollContainerRef.current?.clientHeight,
    ]);

    const refreshTags = useCallback(async () => {
      if (createV2.tagInput.length > 0) {
        createV2.setSuggestedTags({
          ...createV2.suggestedTags,
          [context]: await createV2.getRecommendedStyles(
            createV2.tagInput.split(',').map((tag: string) => tag.trim())
          ),
        });
      } else {
        createV2.setSuggestedTags({
          ...createV2.suggestedTags,
          [context]: await createV2.getRandomGenres(),
        });
      }
    }, [createV2.tagInput, context]);
    return (
      <div className='flex h-auto flex-col'>
        <div
          className={clsx(
            'relative flex flex-row items-start gap-1 transition-[height] duration-500 ease-in-out',
            {
              'mt-2 h-0': !isShown,
              'mt-2 h-[80px]':
                isShown && variant === SuggestedStylesVariants.TwoLine,
              'mt-2 h-[45px]':
                isShown && variant === SuggestedStylesVariants.OneLine,
              'flex-wrap overflow-hidden':
                variant === SuggestedStylesVariants.TwoLine,
            }
          )}
        >
          {createV2.suggestedTags[context].length > 0 && allowRefresh ? (
            <Button
              key='refresh__tags'
              data-testid='refresh-suggested-tags-button'
              className={clsx(
                'mt-[6px] ml-[6px] bg-transparent p-0 text-foreground-secondary/70 backdrop-blur-none enabled:hover:bg-transparent enabled:hover:text-foreground-secondary/80 enabled:hover:backdrop-blur-none',
                {
                  'mb-2': variant === SuggestedStylesVariants.OneLine,
                }
              )}
              icon={RotateReverseIcon}
              variant={ButtonVariant.Glass}
              size={ButtonSize.Mini}
              shape={ButtonShape.Pill}
              onClick={(e) => {
                refreshTags();
                logWebUserEvent({
                  actionName: 'RefreshSuggestedTags',
                  context: {
                    createVersion: CREATE_VERSION,
                    styleContext: context,
                  },
                });
                e.stopPropagation();
              }}
            />
          ) : null}

          {variant === SuggestedStylesVariants.TwoLine
            ? createV2.suggestedTags[context]
                .filter(
                  (tag: string) =>
                    context !== TagSuggestionContexts.SimpleTags ||
                    !createV2.activeTags.includes(tag)
                )
                .map((tag: string, i: number) => (
                  <SuggestedStyle
                    data-testid={`suggested-tag-${i}`}
                    key={tag}
                    tag={tag}
                    onClickStyle={onClickStyle}
                  />
                ))
            : null}

          {variant === SuggestedStylesVariants.OneLine ? (
            <div className='relative w-full'>
              <div
                ref={scrollContainerRef}
                className={clsx(
                  'custom-scrollbar-transparent absolute top-0 left-0 w-full overflow-x-scroll!',
                  {
                    'pb-2': needsCorrectivePadding,
                  }
                )}
                onWheel={(e) => {
                  if (
                    e.deltaY > 0 &&
                    Math.abs(e.deltaY) > Math.abs(e.deltaX) &&
                    scrollContainerRef.current
                  ) {
                    scrollContainerRef.current.scrollLeft -= 20;
                    e.preventDefault();
                  } else if (
                    e.deltaY < 0 &&
                    Math.abs(e.deltaY) > Math.abs(e.deltaX) &&
                    scrollContainerRef.current
                  ) {
                    scrollContainerRef.current.scrollLeft += 20;
                    e.preventDefault();
                  }
                }}
              >
                <div className='flex h-auto w-fit flex-row items-start gap-2'>
                  {createV2.suggestedTags[context]
                    .filter(
                      (tag: string) =>
                        context !== TagSuggestionContexts.SimpleTags ||
                        !createV2.activeTags.includes(tag)
                    )
                    .map((tag: string, i: number) => (
                      <SuggestedStyle
                        data-testid={`suggested-tag-${i}`}
                        icon={icon}
                        key={tag}
                        tag={tag}
                        onClickStyle={onClickStyle}
                      />
                    ))}
                </div>
              </div>
            </div>
          ) : null}
        </div>
      </div>
    );
  }
);
