import * as df from 'date-fns'
import React, { useCallback, useContext, useState } from 'react'
import { View } from 'react-native'

import { colors } from '../Colors'
import { ReactNavigationProps } from '../Navigation'
import { CenteredActivityIndicator } from '../components/CenteredActivityIndicator'
import { ProductImage } from '../components/ProductImage'
import {
  SummaryLegendAbsoluteValueItem,
  SummaryLegendChangePercentageItem,
} from '../components/SummaryLegendItem'
import { TrackDateDataFigure } from '../components/TrackDateDataFigure'
import { ScreenNames } from '../constants/ScreenNames'
import { ArtistContext } from '../contexts/ArtistContext'
import { EventType, sendAnalyticsEvent } from '../hooks/useAnalytics'
import { useEntityStreamsSummary } from '../hooks/useEntityStreams'
import { useTrack } from '../hooks/useTrack'
import {
  TikTokMetric,
  useTrackTikTokMetrics,
} from '../hooks/useTrackTikTokMetrics'
import { useTrackTopCountryCodes } from '../hooks/useTrackTopCountries'
import { Strings } from '../i18n'
import { summaryForDate } from '../streams'
import { defaultTimeInterval, TimeInterval } from '../types/TimeInterval'
import { formatDateString } from '../util/date'
import { GraphScreenContent } from './GraphScreenContent'

export type DaySummary = {
  current: number | null
  changePercentage: number | null
}

const metrics: TikTokMetric[] = ['creations', 'video_views']

const SummaryRow: React.FC<{
  current: number | null
  changePercentage: number | null
  title: string
  changeTitle: string
  color?: string
  infoModal?: {
    text: string
    title: string
  }
}> = ({ color, current, changePercentage, title, changeTitle, infoModal }) => {
  return (
    <View
      style={{
        flexDirection: 'row',
        justifyContent: 'space-between',
      }}
    >
      <SummaryLegendAbsoluteValueItem
        style={{ flex: 1 }}
        label={title}
        labelColor={color ?? colors.metals.metal0}
        infoModal={infoModal}
        value={current ?? undefined}
      />
      <SummaryLegendChangePercentageItem
        label={changeTitle}
        labelColor={color ?? colors.metals.metal0}
        style={{ flex: 1 }}
        changePercentage={(current && changePercentage) ?? undefined}
      />
    </View>
  )
}

export const TrackSummary: React.FC<{
  creations: DaySummary
  views: DaySummary
}> = ({ creations, views }) => (
  <View>
    {creations && (
      <SummaryRow
        title={Strings.Shared.TotalCreations}
        changeTitle={Strings.Shared.TotalCreationsChange}
        current={creations?.current}
        changePercentage={creations?.changePercentage}
        infoModal={{
          title: Strings.TikTok.UserCreations,
          text: Strings.Info.TikTokCreations,
        }}
      />
    )}
    {views && (
      <SummaryRow
        title={Strings.Shared.TotalViews}
        changeTitle={Strings.Shared.TotalViewsChange}
        current={views?.current}
        changePercentage={views?.changePercentage}
        color={colors.platform.apple}
      />
    )}
  </View>
)

export const TrackIntervalSummary: React.FC<{
  selectedInterval: Interval
  isrc: string
  countryCode: string
}> = ({ selectedInterval, isrc, countryCode }) => {
  const [creations, views] = metrics.map((metric) => {
    const data = useMetricsForInterval(
      isrc,
      countryCode,
      metric,
      selectedInterval
    )

    if (data == null) return { current: null, changePercentage: null }

    const current = data?.currentIntervalStreamsSum

    const changePercentage = data.changePercentage
      ? Math.round(data.changePercentage)
      : null

    return { current, changePercentage }
  })

  return <TrackSummary creations={creations} views={views} />
}

const SelectedDateSummary: React.FC<{
  isrc: string
  countryCode: string
  selectedInterval: Interval
  selectedTimeInterval: TimeInterval
  selectedBar: number | null
}> = ({ isrc, countryCode, selectedInterval, selectedBar }) => {
  const selectedDate = selectedBar
    ? formatDateString(df.eachDayOfInterval(selectedInterval)[selectedBar])
    : null

  const [creations, views] = metrics.map((metric) => {
    const currentIntervalCreations = useMetricsForInterval(
      isrc,
      countryCode,
      metric,
      selectedInterval
    )?.currentIntervalStreams
    return currentIntervalCreations != null && selectedDate
      ? summaryForDate(currentIntervalCreations, selectedDate)
      : { current: null, changePercentage: null }
  })

  return <TrackSummary creations={creations} views={views} />
}

export const TrackTikTokScreen: React.FC<
  ReactNavigationProps<ScreenNames.TrackTikTok>
> = ({ navigation, route }) => {
  const screenName = 'Track TikTok Screen'
  const artist = useContext(ArtistContext)
  const { isrc } = route.params
  const countryCode = route.params.market ?? 'worldwide'

  const maxInterval = defaultTimeInterval //Longest interval represented in the graph
  const [selectedTimeInterval, selectTimeInterval] =
    useState<TimeInterval>(maxInterval)

  // Used to inject the top markets into the market selector
  const trackTopMarketCountryCodes = useTrackTopCountryCodes(isrc, 'last28days')

  const { data, retry, refreshing, showToast, error } = useTrack(isrc)

  const onPullToRefresh = () => {
    sendAnalyticsEvent(EventType.PULL_TO_REFRESH, {
      artist_selected: artist.name,
      page: screenName,
      subject: 'user',
      verb: 'refreshed',
      object: 'tiktok',
    })
    retry()
  }

  const handleOnSelectTimeInterval = useCallback(
    (selectedTimeInterval) => {
      sendAnalyticsEvent(EventType.GRAPH_TIMEFRAME_CHANGED, {
        artist_selected: artist.name,
        timeframe_selected: selectedTimeInterval,
        entity_id: isrc,
        screen_name: screenName,
        subject: 'user',
        verb: 'selected',
        object: 'graph_timeframe',
      })
    },
    [artist.name, isrc]
  )

  const track = data?.artist?.track

  return (
    <GraphScreenContent
      screenName={screenName}
      screenTitle={artist.name}
      title={track?.name ?? ''}
      headerImage={
        track?.product != null ? (
          <View style={{ flexDirection: 'row', padding: 8 }}>
            <ProductImage
              product={track.product}
              isExplicit={track.isExplicit}
              size={48}
            />
          </View>
        ) : null
      }
      dsp="tiktok"
      countryCode={countryCode}
      selectedTimeInterval={selectedTimeInterval}
      selectTimeInterval={selectTimeInterval}
      onSelectTimeInterval={handleOnSelectTimeInterval}
      error={error}
      showToast={showToast}
      navigation={navigation}
      retry={onPullToRefresh}
      refreshing={refreshing}
      onPressMarketSelectorButton={() => {
        navigation.navigate('MarketSelector', {
          previousScreen: 'TrackTikTok',
          topMarketCountryCodes: trackTopMarketCountryCodes,
        })
      }}
      renderSelectedDateSummary={(
        selectedInterval: Interval,
        selectedTimeInterval: TimeInterval,
        selectedBar: number | null
      ) => (
        <SelectedDateSummary
          isrc={isrc}
          countryCode={countryCode}
          selectedInterval={selectedInterval}
          selectedTimeInterval={selectedTimeInterval}
          selectedBar={selectedBar}
        />
      )}
      renderSelectedIntervalSummary={(selectedInterval: Interval) => (
        <TrackIntervalSummary
          selectedInterval={selectedInterval}
          isrc={isrc}
          countryCode={countryCode}
        />
      )}
      renderGraph={(
        selectedBar: number | null,
        selectBar: (index: number | null) => void,
        selectedInterval: Interval,
        selectedTimeInterval: TimeInterval,
        selectTimeInterval: (timeInterval: TimeInterval) => void,
        setScrollEnabled: (enabled: boolean) => void
      ) => {
        const [creations, views] = metrics.map((metric) =>
          useMetricsForInterval(isrc, countryCode, metric, selectedInterval)
        )

        if (
          !(creations?.currentIntervalStreams && views?.currentIntervalStreams)
        )
          return <CenteredActivityIndicator />

        return (
          <View style={{ flex: 1 }}>
            <TrackDateDataFigure
              plots={[
                {
                  type: 'line',
                  data: creations.currentIntervalStreams.map((x) => x.data),
                  color: colors.offWhite,
                  lineStrokeWidth: 2.5,
                  axisSide: 'right',
                },
                {
                  type: 'line',
                  data: views.currentIntervalStreams.map((x) => x.data),
                  color: colors.platform.apple,
                  lineStrokeWidth: 2.5,
                  axisSide: 'left',
                },
              ]}
              axisConfig={{
                left: {
                  bounds: { min: 0 },
                  legendLabel: Strings.Shared.Views,
                  color: colors.platform.apple,
                },
                right: {
                  bounds: { min: 0 },
                  legendLabel: Strings.Shared.Creations,
                  color: colors.offWhite,
                },
              }}
              selectBar={selectBar}
              selectedBar={selectedBar}
              selectedInterval={selectedInterval}
              onHoverBar={() => setScrollEnabled(false)}
              onHoverBarEnd={() => setScrollEnabled(true)}
            />
          </View>
        )
      }}
    />
  )
}

function useMetricsForInterval(
  isrc: string,
  countryCode: string,
  metric: TikTokMetric,
  selectedInterval: Interval
) {
  const useMetricsForInterval = (interval: Interval) => {
    const { metric: streams, error } = useTrackTikTokMetrics(
      isrc,
      interval,
      countryCode,
      metric
    )
    return { streams, error }
  }

  const { error, data } = useEntityStreamsSummary(
    selectedInterval,
    useMetricsForInterval
  )

  if (error) throw error

  return data
}
