import React, { memo, useMemo } from 'react';
import type { SyntheticEvent } from 'react';
import Card from '@mui/material/Card';
import Typography from '@mui/material/Typography';
import Tooltip from '@mui/material/Tooltip';
import Grid from '@mui/material/Grid';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import type { ButtonProps } from '@mui/material/Button';
import Divider from '@mui/material/Divider';

import { ASSETS_URL } from '../../../consts/common';
import { HorizontalStackedBars } from '../../horizontal-stacked-bar';
import type { HorizontalStackedBarsProps } from '../../horizontal-stacked-bar';
import clsx from 'clsx';
import { ReactSVG } from 'react-svg';
import createClasses from './styles';
import { Link } from '../../@navigation/link';

type ArrayLengthMutationKeys = 'splice' | 'push' | 'pop' | 'shift' | 'unshift';
type FixedLengthArray<T, L extends number, TObj = [T, ...Array<T>]> = Pick<
  TObj,
  Exclude<keyof TObj, ArrayLengthMutationKeys>
> & {
  readonly length: L;
  [I: number]: T;
  [Symbol.iterator]: () => IterableIterator<T>;
};

export interface InfoCardWithBarsProps {
  /**
   * Callback on clicking the top right button.
   */
  handleClick?: (e: SyntheticEvent<EventTarget>) => void;
  /**
   * Url for top right link.
   */
  href?: string;
  /**
   * Text for the top right button.
   */
  buttonText?: string;
  /**
   * The width of the component.
   */
  rootWidth?: string;
  /**
   * Title of the component.
   */
  title?: string;
  /**
   * Subtitle of the component.
   */
  subtitle?: string;
  /**
   * The data to display inside the component.
   */
  data: {
    textual: FixedLengthArray<{ text: string; value: string | number }, 3>;
    chart: HorizontalStackedBarsProps['data'];
  };
  /**
   * The error message in case of no data.
   */
  errorMessage?: string;
  /**
   * Text for the tooltip on the right side of the title.
   */
  titleTooltipText?: string;
  /**
   * Text for the button tooltip.
   */
  buttonTooltipText?: string;
}

const InfoCardWithBars = (props: InfoCardWithBarsProps) => {
  const {
    subtitle,
    title,
    data,
    rootWidth,
    buttonText,
    handleClick,
    errorMessage,
    titleTooltipText,
    buttonTooltipText,
    href
  } = props;
  const classes = createClasses({ rootWidth: rootWidth || '' });

  const dataWithClasses = useMemo(
    () =>
      data.chart.map(singleData => {
        const { progressBarProps } = singleData;
        const { classes: progressBarClasses } = progressBarProps;
        return {
          ...singleData,
          progressBarProps: {
            ...singleData.progressBarProps,
            classes: {
              marginTop: clsx(classes.marginTop, progressBarClasses?.marginTop),
              marginBottom: clsx(classes.marginBottom, progressBarClasses?.Bottom),
              ...progressBarClasses
            }
          }
        };
      }),
    [classes.marginBottom, classes.marginTop, data.chart]
  );

  const buttonProps: ButtonProps = useMemo(
    () => ({
      color: 'primary',
      variant: 'text',
      onClick: handleClick
    }),
    [handleClick]
  );

  return (
    <Card className={classes.root} component="section">
      <Grid component={Box} pb={2} container>
        <Grid container direction="column" item xs>
          <Grid container alignItems="center" item>
            <Grid container item xs>
              <Grid
                item
                component={Typography}
                color="primary"
                variant="h4"
                className={classes.titleContainer}
              >
                {title}
              </Grid>
              <Grid container alignItems="center" item xs>
                {titleTooltipText && (
                  <Tooltip title={titleTooltipText} data-testid="titleTooltip">
                    <div>
                      <ReactSVG
                        src={`${ASSETS_URL}/icons/icon_help.svg`}
                        className={classes.infoIcon}
                      />
                    </div>
                  </Tooltip>
                )}
              </Grid>
            </Grid>
            {(typeof handleClick === 'function' || typeof href === 'string') && (
              <Grid container item xs justifyContent="flex-end">
                {buttonTooltipText ? (
                  <Tooltip title={buttonTooltipText} data-testid="buttonTooltip">
                    <div className={classes.expandWrapper}>
                      <Button {...buttonProps}>{buttonText}</Button>
                    </div>
                  </Tooltip>
                ) : (
                  <Link
                    href={href}
                    onClick={handleClick}
                    className={classes.topLink}
                    data-testid="topLinkComponent"
                  >
                    {buttonText}
                  </Link>
                )}
              </Grid>
            )}
          </Grid>
          <Grid component={Box} pt={0.5} item>
            <Typography className={classes.subtitle}>{subtitle}</Typography>
          </Grid>
        </Grid>
      </Grid>
      {data.chart.length > 0 ? (
        <>
          <Box display="flex" pb={3} justifyContent="center" alignItems="center">
            {data.textual.map((singleData, index) => {
              const { text, value } = singleData;
              if (index === 1) {
                return (
                  <Box display="flex" key={text}>
                    <Box ml={3}>
                      <Divider orientation="vertical" className={classes.divider} />
                    </Box>
                    <Box px={3} component="p" display="flex" flexDirection="column" margin={0}>
                      <Typography
                        component="span"
                        align="center"
                        variant="body2"
                        className={classes.titleText}
                      >
                        {text}
                      </Typography>
                      <Typography
                        component="span"
                        align="center"
                        className={clsx(classes.textValue, classes.middleTextValue)}
                      >
                        {value}
                      </Typography>
                    </Box>
                    <Box mr={3}>
                      <Divider orientation="vertical" className={classes.divider} />
                    </Box>
                  </Box>
                );
              }
              return (
                <Box display="flex" flexDirection="column" key={text} component="p" margin={0}>
                  <Typography
                    component="span"
                    variant="body2"
                    align="center"
                    className={classes.titleText}
                  >
                    {text}
                  </Typography>
                  <Typography component="span" className={classes.textValue}>
                    {value}
                  </Typography>
                </Box>
              );
            })}
          </Box>

          <HorizontalStackedBars data={dataWithClasses} />
        </>
      ) : (
        <Typography
          component="h3"
          variant="body1"
          color="primary"
          className={classes.centeredErrorMsg}
        >
          {errorMessage}
        </Typography>
      )}
    </Card>
  );
};

InfoCardWithBars.defaultProps = {
  title: 'Active sessions',
  subtitle: '',
  rootWidth: '537px',
  buttonText: 'Expand',
  errorMessage: ''
};

const m = memo(InfoCardWithBars);
export { m as InfoCardWithBars };
