/* eslint-disable react-hooks/rules-of-hooks */
import { getClassNames } from '@websolutespa/bom-core';
import React, { useEffect, useState } from 'react';
import styled, { css } from 'styled-components';
import { tupleNumber } from '../../components/tooltip/tooltip-props';
import { UIStyledComponentProps } from '../../components/types';
import { getCssResponsive } from '../../components/utils';
import { SizeVariant } from '../../variants';
import { RatingIcon } from './rating-icon';

const ratingCountTuple = tupleNumber(2, 3, 4, 5, 6, 7, 8, 9, 10);
const ratingValueTuple = tupleNumber(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
export type RatingValue = typeof ratingValueTuple[number];
export type RatingCount = typeof ratingCountTuple[number];

type Props = {
  size?: SizeVariant;
  className?: string;
  count?: RatingCount | number;
  icon?: React.JSX.Element;
  initialValue?: RatingValue;
  locked?: boolean;
  value?: RatingValue | number;
  onValueChange?: (value: number) => void;
  onLockedChange?: (locked: boolean) => void;
};

export type RatingProps = UIStyledComponentProps<Props>;

const StyledRating = styled.div<RatingProps>`
  display: inline-flex;
  align-items: center;

  .icon {
    width: 1.2em;
    height: 1.2em;
    margin-right: 0.1em;
    color: var(--form-border-color-disabled);
    cursor: pointer;

    & :global(svg) {
      width: 100%;
      height: 100%;
      transform: scale(1);
      transition: transform, color, fill 30ms linear;
    }

    &.hovered {
      color: var(--form-color-hover);

      :global(svg) {
        transform: scale(0.9);
      }
    }
  }

  &.disabled {
    .icon {
      cursor: default;
    }
  }

  ${props => (css`font-size: var(--button-size-${props.size || 'md'});`)}
  ${props => getCssResponsive(props)}
`;

export const Rating: React.FC<RatingProps> = ({
  className = '',
  count = 5 as RatingCount,
  icon = (<RatingIcon />) as React.JSX.Element,
  initialValue = 1 as RatingValue,
  locked: lockedProp = false,
  value: customValue,
  onValueChange,
  onLockedChange,
  ...props
}: React.PropsWithChildren<RatingProps>) => {

  const [value, setValue] = useState<number>(initialValue);

  const [locked, setLocked] = useState<boolean>(lockedProp);

  const onSetLocked = (next: boolean) => {
    setLocked(next);
    onLockedChange && onLockedChange(next);
  };
  const onSetValue = (next: number) => {
    setValue(next);
    const emitValue = next > count ? count : next;
    onValueChange && onValueChange(emitValue);
  };
  const onClick = (index: number) => {
    if (locked) {
      return onSetLocked(false);
    }
    onSetValue(index);
    onSetLocked(true);
  };
  const onMouseEnter = (index: number) => {
    if (locked) {
      return;
    }
    onSetValue(index);
  };

  useEffect(() => {
    if (typeof customValue === 'undefined') {
      return;
    }
    setValue(customValue < 0 ? 0 : customValue);
  }, [customValue]);

  const ratingClassNames = getClassNames('rating', className);
  const getIconClassNames = (index: number) => getClassNames('icon', { hovered: index + 1 <= value });

  return (
    <StyledRating className={ratingClassNames} {...props}>
      {[...Array(count)].map((_, index) => (
        <div key={index} className={getIconClassNames(index)} onMouseEnter={() => onMouseEnter(index + 1)} onClick={() => onClick(index + 1)}>
          {icon}
        </div>
      ))}
    </StyledRating>
  );
};

Rating.displayName = 'Rating';
