import _ from 'lodash'
import React from 'react'
import { StyleProp, Text, View, ViewStyle } from 'react-native'

import { colors, sourceLeanColors } from '../Colors'
import {
  dspNames,
  SourceLean,
  sourceLeans,
  VideoDsp,
  StreamingDsp,
} from '../Consts'
import { TextStyles } from '../Styles'
import { NetworkError } from '../hooks/useNetwork'
import { Strings } from '../i18n'
import { TimeInterval } from '../types/TimeInterval'
import { DspSourcesByDate } from '../types/types'
import { notEmpty, formatPercent, timeRangeInterval } from '../util'
import { formatInterval } from '../util/date'
import { roundNumbersSummingTo100 } from '../util/rounding'
import { DataTile, DataTileText } from './DataTile'
import { BarAndLineFigure } from './figures/BarAndLineFigure'

const LeanPercentage: React.FC<{
  percentage: number
  lean: SourceLean
}> = ({ percentage, lean }) => {
  return (
    <View
      style={{
        justifyContent: 'space-between',
        flexDirection: 'row',
        alignItems: 'center',
        height: 31,
      }}
    >
      <View style={{ flexDirection: 'row', alignItems: 'center' }}>
        <View
          style={{
            borderRadius: 5,
            width: 5,
            height: 5,
            marginRight: 8,
            backgroundColor: sourceLeanColors[lean],
          }}
        />
        <Text style={[TextStyles.body, { color: colors.metals.metal0 }]}>
          {
            {
              leanForward: Strings.Shared.LeanForward,
              leanBack: Strings.Shared.LeanBack,
            }[lean]
          }
        </Text>
      </View>
      <Text style={[TextStyles.bodyBold, { color: sourceLeanColors[lean] }]}>
        {formatPercent(percentage, 0, false)}
      </Text>
    </View>
  )
}

/*
 * aggregate day by day data for all sources of a certain lean/dsp
 */
function leanDspStreams(
  sources: DspSourcesByDate,
  lean: SourceLean,
  dsp: StreamingDsp | VideoDsp
) {
  const byDate = sources.map((item) => {
    const leanSources = item.data?.[dsp]?.[lean]
    const data = leanSources != null ? _.sum(Object.values(leanSources)) : null

    return {
      date: item.date,
      data,
    }
  })

  const sum = _.sum(byDate.map(({ data }) => data))

  return { byDate, sum }
}

function dspSummary(sources: DspSourcesByDate, dsp: StreamingDsp | VideoDsp) {
  const streams = sourceLeans.map((lean) => ({
    lean,
    summary: leanDspStreams(sources, lean, dsp),
  }))

  const total = _.sum(streams.map((lean) => lean.summary.sum))
  const leanPercentages =
    total > 0
      ? streams.map((l) => ({
          lean: l.lean,
          percentage: (l.summary.sum / total) * 100,
        }))
      : null

  const graphData = streams.map(({ lean, summary }) => ({
    yValues: summary.byDate.map(({ data }) => data),
    strokeColor: sourceLeanColors[lean],
  }))

  const maxYValue = graphData.reduce(
    (max, { yValues }) => Math.max(max, ...yValues.filter(notEmpty)),
    0
  )

  return { maxYValue, graphData, leanPercentages }
}

/**
 * A tile representing entity (track/video) stream sources for a dsp
 */
export const EntityStreamSourcesTile: React.FC<{
  dsp: StreamingDsp | VideoDsp
  timeInterval: TimeInterval
  onPress: () => void
  style?: StyleProp<ViewStyle>
  title: string
  sources?: DspSourcesByDate
  error: NetworkError | null
}> = ({ sources, error, dsp, timeInterval, onPress, style, title }) => {
  const currentInterval = timeRangeInterval(timeInterval)
  const summary = sources != null ? dspSummary(sources, dsp) : null
  const percentagesSummingTo100 = roundNumbersSummingTo100(
    summary?.leanPercentages?.map(({ percentage }) => percentage) ?? []
  )

  return (
    <DataTile
      dsp={dsp}
      title={title}
      subTitle={formatInterval(currentInterval)}
      onPress={onPress}
      style={[{ minHeight: 364 }, style]}
      error={error}
    >
      {summary != null ? (
        summary.leanPercentages != null ? (
          <>
            <View style={{ flex: 1, flexDirection: 'row', marginBottom: 24 }}>
              <BarAndLineFigure
                plots={summary.graphData.map(({ yValues, strokeColor }) => ({
                  type: 'line',
                  data: yValues,
                  color: strokeColor,
                  lineStrokeWidth: 2.5,
                  axisSide: 'right',
                }))}
                axisConfig={{
                  right: {
                    color: colors.offWhite,
                  },
                }}
                grid
                valueExtractor={(item) => item}
              />
            </View>
            {summary.leanPercentages.map(({ lean }, index) => (
              <LeanPercentage
                key={lean}
                percentage={percentagesSummingTo100[index]}
                lean={lean}
              />
            ))}
          </>
        ) : (
          <DataTileText
            text={Strings.Shared.TrackNoStreamSourcesForDsp.replace(
              '%s',
              dspNames[dsp]
            )}
          />
        )
      ) : null}
    </DataTile>
  )
}
