import { Skeleton } from "@mui/lab";
import { Box, Grid, Typography } from "@mui/material";
import PropTypes from "prop-types";
import React, { useRef } from "react";
import { AutoSizer, List } from "react-virtualized";
import { PositiveNegativeProgressBar } from "../../Common";
import {
  Container,
  SkeletonBarWrapper,
  StyledBarItemsContainer,
  StyledPercentageRange,
  StyledTitle,
} from "./styles";

const PositiveNegativeProgressBarChart = ({
  data,
  direction = "horizontal",
  title,
  showPercentageValue,
  barItemHeight,
  barItemWidth,
  chartHeight,
  chartWidth,
  showPercentageRange,
  overscanRowCount = 10,
  rowHeight = 20,
  onClick,
  minRange = 0,
  maxRange = 0,
  labelPosition = "left",
  ...otherProps
}) => {
  const isVertical = direction === "vertical";
  const progressbarRef = useRef([]);

  const getRange = (num) => {
    if (num === 0) return [0];

    const step = 1 / 3;
    const range = [];
    let rangeSum = 0;

    for (let i = 0; rangeSum + step <= 1; i++) {
      rangeSum += step;
      range.push(rangeSum);
    }

    return range;
  };

  const renderTitle = () => {
    if (isVertical)
      return (
        <Box sx={{ display: "flex", justifyContent: "center" }}>
          <StyledTitle variant="h6">{title}</StyledTitle>
        </Box>
      );

    return (
      <Grid container alignItems="center">
        <Grid item xs={3} />
        <Grid item xs={8}>
          <Box paddingLeft="10px" paddingRight="10px">
            <StyledTitle variant="h6" style={{ textAlign: "center" }}>
              {title}
            </StyledTitle>
          </Box>
        </Grid>
        <Grid item xs={1} />
      </Grid>
    );
  };

  const renderPercentageRange = () => {
    const min = getRange(minRange);
    const max = getRange(maxRange);
    return (
      <Box display="flex" flexDirection="column">
        <StyledPercentageRange
          isvertical={isVertical ? "true" : "false"}
          height={"100%"}
          width={"100%"}
        >
          {min.reverse().map((range) => (
            <Typography variant="caption">{`${range.toFixed(2)}%`}</Typography>
          ))}
          <Typography variant="caption">0%</Typography>
          {max.map((range) => (
            <Typography variant="caption">{`${range.toFixed(2)}%`}</Typography>
          ))}
        </StyledPercentageRange>
        {isVertical && <Box sx={{ height: "48px" }} />}
      </Box>
    );
  };

  const renderHorizontalPercentageRange = () => {
    return (
      <Grid container alignItems="center" marginBottom="20px">
        <Grid item xs={3} />
        <Grid item xs={8} paddingLeft="10px">
          {renderPercentageRange()}
        </Grid>
        <Grid item xs={1} />
      </Grid>
    );
  };

  const rowRenderer = ({ index, isScrolling, key, style }) => {
    if (isScrolling) {
      return (
        <SkeletonBarWrapper key={key} style={style}>
          <Skeleton width="20%" />
          <Skeleton width="79%" />
        </SkeletonBarWrapper>
      );
    }
    return (
      <Box
        ref={(element) => progressbarRef.current.push(element)}
        key={key}
        style={style}
      >
        <PositiveNegativeProgressBar
          key={`positive-negative-bar-item-${data[index].id}`}
          width={barItemWidth}
          height={barItemHeight}
          showPercentageValue={showPercentageValue}
          direction={direction}
          onClick={onClick}
          labelPosition={labelPosition}
          {...data[index]}
        />
      </Box>
    );
  };

  const renderBarItems = () => {
    return (
      <StyledBarItemsContainer isvertical={isVertical ? "true" : "false"}>
        {showPercentageRange &&
          !isVertical &&
          renderHorizontalPercentageRange()}
        {!isVertical ? (
          <AutoSizer>
            {({ width, height }) => (
              <List
                height={height}
                overscanRowCount={overscanRowCount}
                rowCount={data.length}
                rowHeight={rowHeight * 2}
                rowRenderer={rowRenderer}
                width={width}
              />
            )}
          </AutoSizer>
        ) : (
          <>
            {data.map((_data) => (
              <PositiveNegativeProgressBar
                key={`positive-negative-bar-item-${_data.id}`}
                width={barItemWidth}
                height={barItemHeight}
                showPercentageValue={showPercentageValue}
                direction={direction}
                onClick={onClick}
                {..._data}
              />
            ))}
            {showPercentageRange && isVertical && renderPercentageRange()}
          </>
        )}
      </StyledBarItemsContainer>
    );
  };

  return (
    <Container {...otherProps} height={chartHeight} width={chartWidth}>
      {title && renderTitle()}
      {data.length > 0 && renderBarItems()}
    </Container>
  );
};

PositiveNegativeProgressBarChart.propTypes = {
  data: PropTypes.arrayOf(
    PropTypes.shape({
      id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
      label: PropTypes.string,
      negativeValue: PropTypes.number,
      positiveValue: PropTypes.number,
      resultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
      resultColor: PropTypes.string,
    })
  ),
  direction: PropTypes.oneOf(["horizontal", "vertical"]),
  title: PropTypes.string,
  showPercentageValue: PropTypes.bool,
  chartHeight: PropTypes.string,
  chartWidth: PropTypes.string,
  barItemHeight: PropTypes.string,
  barItemWidth: PropTypes.string,
  showPercentageRange: PropTypes.bool,
  onClick: PropTypes.func,
  overscanRowCount: PropTypes.number,
  minRange: PropTypes.number,
  maxRange: PropTypes.number,
  labelPosition: PropTypes.oneOf(["top", "left"]),
};

export default PositiveNegativeProgressBarChart;
