import { groupBy, map, mapValues, sum } from 'lodash'
import React, { useCallback, useMemo } from 'react'

import { demographicsColorsByDsp } from '../Colors'
import { Dsp } from '../Consts'
import { DemographicsAgeBand, AgeRange } from '../graphql/__generated__/sdk'
import { Strings } from '../i18n'
import { formatAgeRange, parseAgeRange } from '../util'
import { roundNumbersSummingTo100 } from '../util/rounding'
import {
  DonutFigure,
  DonutFigureData,
  DonutFigureItem,
} from './figures/DonutFigure'

export function getTotalStreamsFromDemographicsData(
  dspDemographics: DemographicsAgeBand[]
): number {
  const genderPercentages = mapValues(
    groupBy(dspDemographics, 'ageRange'),
    (ageRanges) => sum(ageRanges.map(({ percentage }) => percentage))
  )

  return sum(Object.values(genderPercentages))
}

function roundAgePercentages(agePercentages: DonutFigureData) {
  const roundedValues = roundNumbersSummingTo100(
    agePercentages.map(({ percentage }) => percentage)
  )

  return agePercentages.map((genderPercentage, i) => ({
    ...genderPercentage,
    percentage: roundedValues[i],
  }))
}

function getGraphData(
  dspDemographics: DemographicsAgeBand[],
  dsp: Dsp
): DonutFigureData {
  const valuePerAgeGroups = map(
    groupBy(dspDemographics, ({ ageRange }) => formatAgeRange(ageRange, dsp)),
    (ageBands, formattedAgeRange) => {
      const percentage = ageBands.reduce(
        (memo, { percentage }) => memo + (percentage ?? 0),
        0
      )

      return {
        key: formattedAgeRange,
        percentage,
      }
    }
  ).sort((a, b) => b.percentage - a.percentage)

  return roundAgePercentages(valuePerAgeGroups)
}

export const AgeDemographics: React.FC<{
  dsp: Dsp
  dspDemographics: DemographicsAgeBand[]
  selectedAgeRange?: AgeRange | null
  onSelectAgeRange?: (ageRange: AgeRange | null) => void
}> = ({ dsp, dspDemographics, selectedAgeRange, onSelectAgeRange }) => {
  const graphData = useMemo(
    () => (dspDemographics ? getGraphData(dspDemographics, dsp) : []),
    [dspDemographics, dsp]
  )

  const selectedItem = useMemo(
    () =>
      selectedAgeRange !== undefined
        ? graphData.find(
            ({ key }) => key === formatAgeRange(selectedAgeRange, dsp)
          )
        : undefined,
    [graphData, selectedAgeRange, dsp]
  )

  const handleSelectItem = useCallback(
    (item: DonutFigureItem) => onSelectAgeRange?.(parseAgeRange(item.key)),
    [onSelectAgeRange]
  )

  return (
    <DonutFigure
      title={Strings.Shared.AgeGroup}
      data={graphData}
      legendProps={{
        keyHeader: Strings.Shared.AgeGroup,
        valueHeader: Strings.Shared.TotalPercentage,
        colors: demographicsColorsByDsp[dsp],
      }}
      selectedItem={selectedItem}
      onSelectItem={handleSelectItem}
    />
  )
}
