import React, { useContext } from 'react'
import * as df from 'date-fns'
import { Text, View } from 'react-native'
import { colorsV2 } from '../Colors'
import { DiffNumber } from '../components/DiffNumber'
import { ProductImage } from '../components/ProductImage'
import { ScreenNames } from '../constants/ScreenNames'
import { ArtistContext } from '../contexts/ArtistContext'
import { EventType, sendAnalyticsEvent } from '../hooks/useAnalytics'
import {
  IntervalSummary,
  useEntityStreamsSummary,
} from '../hooks/useEntityStreams'
import { useTrack } from '../hooks/useTrack'
import { useTrackTopCountryCodes } from '../hooks/useTrackTopCountries'
import { Strings } from '../i18n'
import { ReactNavigationProps } from '../Navigation'
import { TextStylesV2 } from '../Styles'
import { changePercent, formatCount, timeRangeInterval } from '../util'
import { formatDateString, parseDateString } from '../util/date'
import { GraphScreenContent } from './GraphScreenContent'
import { TrackDateDataFigure } from '../components/TrackDateDataFigure'
import {
  TikTokMetric,
  useTrackTikTokMetrics,
} from '../hooks/useTrackTikTokMetrics'
import { TimeInterval } from '../types/TimeInterval'
import { InfoModal } from '../components/InfoModal'
import { TouchableOpacity } from 'react-native-gesture-handler'
import Info from '../icons/Info'

type DaySummary = { current: number | null; changePercentage: number | null }
type CreationsSummary = DaySummary
type ViewsSummary = DaySummary

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

type RowSummary = {
  current: number | null
  changePercentage: number | null
  title: string
  color?: string
  infoModalText?: string
  infoModalTitle?: string
}
const SummaryRow: React.FC<RowSummary> = (props) => {
  const { current, changePercentage, title, infoModalText, infoModalTitle } =
    props
  const color = props.color ?? colorsV2.metals.metal0
  const titleStyle = {
    ...TextStylesV2.tiny,
    ...{ color },
  }
  const detailStyle = {
    ...TextStylesV2.bodyBold,
    color: colorsV2.white,
  }

  const detail = current ? formatCount(current) : Strings.Shared.NotApplicable

  return (
    <View style={{ flexDirection: 'row', justifyContent: 'space-between' }}>
      <View style={{ flex: 1 }}>
        <View style={{ flexDirection: 'row', alignItems: 'center' }}>
          <Text style={titleStyle}>{title}</Text>
          {infoModalTitle != null && infoModalText != null && (
            <InfoModal
              title={infoModalTitle}
              body={{ type: 'string', text: infoModalText }}
            >
              {(open) => (
                <TouchableOpacity
                  onPress={open}
                  style={{ paddingHorizontal: 10 }}
                >
                  <Info />
                </TouchableOpacity>
              )}
            </InfoModal>
          )}
        </View>

        <Text style={detailStyle}>{detail}</Text>
      </View>
      <View style={{ flex: 1 }}>
        <View>
          <Text style={titleStyle}>{Strings.Shared.Change}</Text>
          {current && changePercentage ? (
            <DiffNumber
              value={changePercentage}
              size="large"
              type="percentage"
            />
          ) : (
            <Text style={detailStyle}>{Strings.Shared.NotApplicable}</Text>
          )}
        </View>
      </View>
    </View>
  )
}

export const TrackSummary: React.FC<{
  creations: CreationsSummary
  views: ViewsSummary
}> = ({ creations, views }) => (
  <View>
    {creations && (
      <SummaryRow
        title={Strings.Shared.Creations}
        current={creations?.current}
        changePercentage={creations?.changePercentage}
        infoModalTitle={Strings.TikTok.UserCreations}
        infoModalText={Strings.Info.TikTokCreations}
      />
    )}
    {views && (
      <SummaryRow
        title={Strings.Shared.Views}
        current={views?.current}
        changePercentage={views?.changePercentage}
        color={colorsV2.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} />
}

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.countryCode ?? 'worldwide'

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

  const { data, retry, refreshing, showToast, error } = useTrack(isrc, () =>
    sendAnalyticsEvent(EventType.PULL_TO_REFRESH, {
      artist_selected: artist.name,
      page: screenName,
      subject: 'user',
      verb: 'refreshed',
      object: 'tiktok',
    })
  )

  const track = data?.track

  const maxInterval = timeRangeInterval('last28days')

  const [creations, views] = metrics.map((metric) =>
    useMetricsForInterval(isrc, countryCode, metric, maxInterval)
  )

  return (
    <GraphScreenContent
      screenTitle={artist.name}
      title={track?.name ?? ''}
      headerImage={
        track?.product != null ? (
          <View style={{ flexDirection: 'row', padding: 8 }}>
            <ProductImage
              product={track.product}
              isExplicit={false}
              size={48}
            />
          </View>
        ) : null
      }
      dsp={'tiktok'}
      countryCode={countryCode}
      onSelectTimeInterval={(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',
        })
      }}
      error={error}
      showToast={showToast}
      navigation={navigation}
      retry={retry}
      refreshing={refreshing}
      onPressMarketSelectorButton={() => {
        navigation.navigate('MarketSelector', {
          previousScreen: 'TrackTikTok',
          topMarketCountryCodes: trackTopMarketCountryCodes,
        })
      }}
      renderSelectedDateSummary={(selectedDate: string) => {
        const summarize = ({
          currentIntervalStreams: metric,
        }: IntervalSummary) => {
          const empty = { current: null, changePercentage: null }
          if (!selectedDate) return empty

          const getMetricForDate = (selectedDate: string) =>
            metric.find(({ date }) => date === selectedDate)?.data

          const current = getMetricForDate(selectedDate)
          if (current == null) return empty

          const yesterday = formatDateString(
            df.subDays(parseDateString(selectedDate), 1)
          )

          const previous = getMetricForDate(yesterday)
          if (previous == null) return { current, changePercentage: null }

          const changePercentage = Math.round(changePercent(current, previous))
          return { current, changePercentage }
        }

        const [creationSummary, viewSummary] = [creations, views].map(summarize)

        return <TrackSummary creations={creationSummary} views={viewSummary} />
      }}
      renderSelectedIntervalSummary={(selectedInterval: Interval) => (
        <TrackIntervalSummary
          selectedInterval={selectedInterval}
          isrc={isrc}
          countryCode={countryCode}
        />
      )}
      renderGraph={(
        selectedDate: string,
        selectDate: (date: string) => void,
        selectedInterval: Interval,
        selectedTimeInterval: TimeInterval,
        selectTimeInterval: (timeInterval: TimeInterval) => void,
        setScrollEnabled: (enabled: boolean) => void
      ) => {
        if (
          !(creations?.currentIntervalStreams && views?.currentIntervalStreams)
        )
          return

        return (
          <View style={{ flex: 1 }}>
            <TrackDateDataFigure
              maxIntervalBar={creations.currentIntervalStreams}
              maxIntervalLine={views.currentIntervalStreams}
              lineAxisConfig={{ bounds: { min: 0 } }}
              selectDate={selectDate}
              selectedDate={selectedDate}
              selectedTimeInterval={selectedTimeInterval}
              selectTimeInterval={selectTimeInterval}
              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
}
