import { useTheme } from '@emotion/react';
import type { ReactElement } from 'react';
import React from 'react';

import Typography from '../../Typography';

import Box from '../../Box';
import { MAX_PROGRESS_VALUE, MIN_PROGRESS_VALUE } from './constants';
import {
  useValidateSegmentedBarData,
  useValidateSegmentedBarLegendDisplayValues,
  useValidateSegmentedBarStyleConfig,
} from './hooks/validation';
import { useSegmentedBarColors } from './hooks/colors';
import LegendItem from './Legend';
import { LegendBox } from './StyledLegend';
import {
  StyledEmptyText,
  StyledHeader,
  StyledSegment,
  StyledTrack,
} from './StyledSegmentedBar';
import type { ProgressSegmentedBarProps } from './types';
import { getTextComponent } from './utils';

const ProgressSegmentedBar = ({
  data,
  headerConfig,
  emptyText,
  legendConfig,
  styleConfig,
  style,
  testID,
  collapsable,
  ...nativeProps
}: ProgressSegmentedBarProps): ReactElement => {
  const values = React.useMemo(() => data.map((s) => s.data), [data]);
  useValidateSegmentedBarData({ dataLength: data.length, values });

  const legendDisplayValues = useValidateSegmentedBarLegendDisplayValues({
    dataLength: data.length,
    legendConfig,
    fallbackValues: values,
  });

  useValidateSegmentedBarStyleConfig({
    dataSeries: data,
    customSeries: styleConfig?.series,
  });

  const theme = useTheme();
  const totalPercent = React.useMemo(
    () => values.reduce((acc, value) => acc + value, 0),
    [values]
  );

  const ariaValueMax =
    totalPercent > MAX_PROGRESS_VALUE ? totalPercent : MAX_PROGRESS_VALUE;

  const remainderPercent = React.useMemo(() => {
    return totalPercent >= MAX_PROGRESS_VALUE
      ? 0
      : MAX_PROGRESS_VALUE - totalPercent;
  }, [totalPercent]);
  const segmentColors = useSegmentedBarColors({
    dataSeries: data,
    customSeries: styleConfig?.series,
  });

  const headerRight = React.useMemo(
    () =>
      getTextComponent(
        headerConfig?.right,
        <Typography.Caption intent="muted">
          {headerConfig?.right}
        </Typography.Caption>
      ),
    [headerConfig?.right]
  );

  const showHeader = Boolean(headerConfig?.left || headerRight);
  const showLegend = Boolean(
    legendConfig && Object.keys(legendConfig).length > 0
  );
  const showEmptyText = Boolean(!data.length && emptyText);

  return (
    <Box
      {...nativeProps}
      style={style}
      testID={testID}
      collapsable={collapsable || false}
    >
      {showHeader ? (
        <StyledHeader testID={testID ? `${testID}-header` : undefined}>
          {headerConfig?.left ? (
            <Typography.Body
              variant="regular-bold"
              testID={testID ? `${testID}-header-left` : undefined}
            >
              {headerConfig.left}
            </Typography.Body>
          ) : null}

          {headerRight ? (
            <Box testID={testID ? `${testID}-header-right` : undefined}>
              {headerRight}
            </Box>
          ) : null}
        </StyledHeader>
      ) : null}

      <StyledTrack
        testID={testID ? `${testID}-track` : undefined}
        accessibilityRole="progressbar"
        accessibilityValue={{
          min: MIN_PROGRESS_VALUE,
          max: ariaValueMax,
          now: totalPercent,
        }}
      >
        {data.map((s, index) => {
          const segmentColor = segmentColors[index % segmentColors.length];

          return (
            <StyledSegment
              key={`${s.label}-${segmentColor}`}
              themeColor={segmentColor}
              themeWidthPercent={s.data}
              testID={testID ? `${testID}-segment-${s.label}` : undefined}
            />
          );
        })}

        {remainderPercent > 0 ? (
          <StyledSegment
            key="remainder"
            themeColor={
              theme.__hd__.progress.colors.segmentedRemainderBackground
            }
            themeWidthPercent={remainderPercent}
            testID={testID ? `${testID}-segment-remainder` : undefined}
          />
        ) : null}
      </StyledTrack>

      {showEmptyText ? (
        <StyledEmptyText
          intent="muted"
          testID={testID ? `${testID}-empty-text` : undefined}
        >
          {emptyText}
        </StyledEmptyText>
      ) : null}

      {showLegend ? (
        <LegendBox testID={testID ? `${testID}-legend` : undefined}>
          {data.map((item, index) => (
            <LegendItem
              key={`${item.label}-${
                segmentColors[index % segmentColors.length]
              }`}
              title={item.label}
              color={segmentColors[index % segmentColors.length]}
              displayValue={legendDisplayValues[index]}
              testID={testID ? `${testID}-legend-${item.label}` : undefined}
            />
          ))}
        </LegendBox>
      ) : null}
    </Box>
  );
};

export default ProgressSegmentedBar;
