import { createURL } from 'expo-linking'
import { flatten } from 'lodash'
import React, { useCallback, useContext, useState } from 'react'

import { Dsp, StreamingDsp } from '../Consts'
import { ReactNavigationProps } from '../Navigation'
import { EntityStreamsGraphScreenContent } from '../components/EntityStreamsGraphScreenContent'
import { ProductImage } from '../components/ProductImage'
import { ScreenNames } from '../constants/ScreenNames'
import { ArtistContext } from '../contexts/ArtistContext'
import { EventType, sendAnalyticsEvent } from '../hooks/useAnalytics'
import { useRegion } from '../hooks/useRegions'
import { useTrack } from '../hooks/useTrack'
import {
  generateStreamQueries,
  mapToSummaries,
  useTrackStreams,
} from '../hooks/useTrackStreams'
import { useTrackTopCountryCodes } from '../hooks/useTrackTopCountries'
import { localizedCountryName, Strings } from '../i18n'
import { ScreenPaths } from '../linking'
import { shareContextMenuItem } from '../share'
import { defaultTimeInterval, TimeInterval } from '../types/TimeInterval'

export const TrackStreamsGraphScreen: React.FC<
  ReactNavigationProps<ScreenNames.TrackStreamsGraph>
> = ({ navigation, route }) => {
  const screenName = 'Track Streams Graph Screen'
  const { isrc, dsp } = route.params
  const artist = useContext(ArtistContext)
  const countryCode = route.params.market ?? 'worldwide'
  const region = useRegion(countryCode)

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

  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: 'track',
    })
    retry()
  }

  const track = data?.artist?.track

  const trackTopMarketCountryCodes = useTrackTopCountryCodes(
    isrc,
    defaultTimeInterval
  )

  const title =
    countryCode === 'worldwide'
      ? Strings.Shared.StreamsWorldwide
      : region != null
      ? Strings.Shared.StreamsInMarket.replace(
          '%s',
          localizedCountryName(region)
        )
      : Strings.Shared.Streams

  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 getSummaryData = (interval: Interval, dsp: Dsp | 'all') => {
    const queries = generateStreamQueries(
      dsp as StreamingDsp,
      countryCode,
      interval
    )

    const response = useTrackStreams(isrc, flatten(queries))

    return mapToSummaries(
      response,
      queries.map((current) => current[0]?.dspId as StreamingDsp)
    )
  }

  return (
    <EntityStreamsGraphScreenContent
      screenName={screenName}
      screenTitle={track?.name}
      title={title}
      headerImage={
        track != null ? (
          <ProductImage
            product={track.product}
            isExplicit={track.isExplicit}
            size={48}
          />
        ) : null
      }
      dsp={dsp}
      countryCode={countryCode}
      selectedTimeInterval={selectedTimeInterval}
      selectTimeInterval={selectTimeInterval}
      onSelectTimeInterval={handleOnSelectTimeInterval}
      getSummaryData={getSummaryData}
      error={error}
      showToast={showToast}
      navigation={navigation}
      retry={onPullToRefresh}
      refreshing={refreshing}
      onPressMarketSelectorButton={() => {
        navigation.navigate('MarketSelector', {
          previousScreen: 'TrackStreamsGraph',
          topMarketCountryCodes: trackTopMarketCountryCodes,
        })
      }}
      totalLabel={Strings.Shared.TotalStreams}
      gainLossLabel={Strings.Shared.TotalStreamsGainLoss}
      changeLabel={Strings.Shared.TotalStreamsChange}
      contextMenuItems={[
        shareContextMenuItem(
          createURL(
            ScreenPaths['TrackStreamsGraph'](artist.sonyArtistId, isrc),
            {
              queryParams: {
                time_interval: selectedTimeInterval,
                market: countryCode,
                dsp,
              },
            }
          ),
          {
            message: Strings.ShareContent.TrackStreamsGraphScreen.message
              .replace('${artistName}', artist.name)
              .replace('${trackName}', track?.name ?? ''),
          }
        ),
      ]}
    />
  )
}
