import * as df from 'date-fns'
import React from 'react'
import { StyleSheet, Text, View } from 'react-native'
import { colorsV2 } from '../Colors'
import { ChangePlusMinusAndPercent } from '../components/ChangePlusMinusAndPercent'
import { DetailBarGraph } from '../components/DetailBarGraph'
import { DiffNumber } from '../components/DiffNumber'
import { ScreenNames } from '../constants/ScreenNames'
import { Dsp, StreamingDsp, streamingDsps } from '../Consts'
import { DateData } from '../DateData'
import {
  StreamsByDateResult,
  useEntityStreamsSummary,
} from '../hooks/useEntityStreams'
import { Strings } from '../i18n'
import { NavigationProp } from '../Navigation'
import { GraphScreenContent } from '../screens/GraphScreenContent'
import { TextStylesV2 } from '../Styles'
import { TimeInterval } from '../types/TimeInterval'
import {
  changePercent,
  formatCount,
  formatCountShort,
  timeRangeInterval,
} from '../util'
import { formatDateString, parseDateString } from '../util/date'
import { DspStreams } from './DspStreams'
import { NetworkError } from './useNetwork'

const styles = StyleSheet.create({
  text: { ...TextStylesV2.tiny, ...{ color: colorsV2.metals.metal0 } },
})

/**
 *
 * Display information for the currently selected time interval
 */
export const IntervalSummary: React.FC<{
  changePercentage: number | null
  currentIntervalStreamsSum: number
}> = ({ changePercentage, currentIntervalStreamsSum }) => {
  return (
    <View>
      <Text style={[TextStylesV2.h3, { color: colorsV2.white }]}>
        {formatCountShort(currentIntervalStreamsSum)}
      </Text>
      {changePercentage !== null && (
        <ChangePlusMinusAndPercent changePercentage={changePercentage} />
      )}
    </View>
  )
}

/**
 *
 * Display information for the currently selected day
 */
export const DaySummary: React.FC<{
  currentValue: number
  previousValue: number | null
  currentValuePerDsp?: {
    dsp: StreamingDsp
    streams: number
  }[]
}> = ({ currentValue, previousValue, currentValuePerDsp }) => {
  return (
    <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
      <View style={{ flex: 1 }}>
        <Text style={styles.text}>{Strings.Shared.Total}</Text>
        <Text style={[TextStylesV2.bodyBold, { color: colorsV2.white }]}>
          {formatCount(currentValue)}
        </Text>
        {currentValuePerDsp != null ? (
          <View>
            {currentValuePerDsp.map(({ dsp, streams }) => (
              <DspStreams key={dsp} dsp={dsp} streams={streams} gap={21} />
            ))}
          </View>
        ) : null}
      </View>
      {previousValue != null && (
        <View style={{ flex: 1 }}>
          <View>
            <Text style={styles.text}>{Strings.Shared.GainLoss}</Text>
            <DiffNumber
              value={currentValue - previousValue}
              size="large"
              type="total"
            />
          </View>
          <View>
            <Text style={styles.text}>{Strings.Shared.Change}</Text>
            {currentValue != null &&
              previousValue != null &&
              previousValue !== 0 && (
                <DiffNumber
                  value={Math.round(changePercent(currentValue, previousValue))}
                  size="large"
                  type="percentage"
                />
              )}
          </View>
        </View>
      )}
    </View>
  )
}

const SelectedDateSummary: React.FC<{
  maxIntervalStreams: DateData<number>[]
  selectedDate: string
  dsp: Dsp | 'all'
  useEntityStreams: (
    interval: Interval,
    dsp: Dsp | 'all'
  ) => StreamsByDateResult
  maxInterval: TimeInterval
}> = ({
  maxIntervalStreams,
  selectedDate,
  dsp,
  useEntityStreams,
  maxInterval,
}) => {
  const selectedDateStreams =
    maxIntervalStreams?.find(({ date }) => date === selectedDate)?.data ?? 0
  const dayBeforeSelectedDateStreams = selectedDate
    ? maxIntervalStreams?.find(
        ({ date }) =>
          date ===
          formatDateString(df.subDays(parseDateString(selectedDate), 1))
      )?.data ?? null
    : null
  const selectedDateStreamsPerDsp =
    dsp === 'all'
      ? streamingDsps.map((dsp) => ({
          dsp,
          streams:
            useEntityStreams(
              timeRangeInterval(maxInterval),
              dsp
            )?.streams?.find(({ date }) => date === selectedDate)?.data ?? 0,
        }))
      : null
  return (
    <DaySummary
      currentValue={selectedDateStreams}
      previousValue={dayBeforeSelectedDateStreams}
      currentValuePerDsp={selectedDateStreamsPerDsp}
    />
  )
}

const SelectedIntervalSummary: React.FC<{
  useEntityStreams: (interval: Interval) => StreamsByDateResult
  selectedInterval: Interval
}> = ({ useEntityStreams, selectedInterval }) => {
  const selectedIntervalSummary = useEntityStreamsSummary(
    selectedInterval,
    useEntityStreams
  )?.data
  return selectedIntervalSummary != null ? (
    <IntervalSummary {...selectedIntervalSummary} />
  ) : null
}

export const EntityStreamsGraphScreenContent: React.FC<{
  screenTitle?: string
  title: string
  headerImage: React.ReactNode
  dsp: Dsp | 'all'
  countryCode: string
  onSelectTimeInterval: (timeInterval: TimeInterval) => void
  useEntityStreams: (
    interval: Interval,
    dsp: Dsp | 'all'
  ) => StreamsByDateResult
  error: NetworkError | null
  showToast: boolean
  navigation: NavigationProp<ScreenNames>
  retry: () => void
  refreshing: boolean
  onPressMarketSelectorButton?: () => void
}> = ({
  screenTitle,
  title,
  headerImage,
  dsp,
  countryCode,
  onSelectTimeInterval,
  useEntityStreams,
  error,
  showToast,
  navigation,
  retry,
  refreshing,
  onPressMarketSelectorButton,
}) => {
  const maxInterval = 'last28days' // Longest interval represented in the bar graph
  const useEntityStreamsForDsp = (interval: Interval) =>
    useEntityStreams(interval, dsp)

  const maxIntervalStreams = useEntityStreamsSummary(
    timeRangeInterval(maxInterval),
    useEntityStreamsForDsp
  )?.data?.currentIntervalStreams

  return (
    <GraphScreenContent
      screenTitle={screenTitle}
      title={title}
      headerImage={headerImage}
      dsp={dsp}
      countryCode={countryCode}
      onSelectTimeInterval={onSelectTimeInterval}
      error={error}
      showToast={showToast}
      navigation={navigation}
      retry={retry}
      refreshing={refreshing}
      onPressMarketSelectorButton={onPressMarketSelectorButton}
      renderSelectedDateSummary={(selectedDate: string) => (
        <SelectedDateSummary
          maxIntervalStreams={maxIntervalStreams}
          selectedDate={selectedDate}
          dsp={dsp}
          useEntityStreams={useEntityStreams}
          maxInterval={maxInterval}
        />
      )}
      renderSelectedIntervalSummary={(selectedInterval: Interval) => (
        <SelectedIntervalSummary
          useEntityStreams={useEntityStreamsForDsp}
          selectedInterval={selectedInterval}
        />
      )}
      renderGraph={(
        selectedDate: string,
        selectDate: (date: string) => void,
        selectedInterval: Interval,
        selectedTimeInterval: TimeInterval,
        selectTimeInterval: (timeInterval: TimeInterval) => void,
        setScrollEnabled: (enabled: boolean) => void
      ) => {
        return (
          maxIntervalStreams != null && (
            <View style={{ flex: 1 }}>
              <DetailBarGraph
                maxIntervalValues={maxIntervalStreams}
                selectDate={selectDate}
                selectedDate={selectedDate}
                selectedTimeInterval={selectedTimeInterval}
                selectTimeInterval={selectTimeInterval}
                selectedInterval={selectedInterval}
                onHoverBar={() => setScrollEnabled(false)}
                onHoverBarEnd={() => setScrollEnabled(true)}
              />
            </View>
          )
        )
      }}
    />
  )
}
