import React, { useContext } from 'react'
import { RefreshControlProps } from 'react-native'

import { ReactNavigationProps } from '../Navigation'
import { CommonScreenContainer } from '../components/CommonScreenContainer'
import { ErrorBoundary } from '../components/ErrorBoundary'
import { HeaderNav } from '../components/HeaderNav'
import { ProductDetailHeading } from '../components/ProductDetailHeading'
import { TrackListSkeleton } from '../components/Skeleton'
import { TrackList } from '../components/TrackList'
import { StreamsListItem } from '../components/listitems/StreamsListItem'
import { ScreenNames } from '../constants/ScreenNames'
import { ArtistContext } from '../contexts/ArtistContext'
import { EventType, sendAnalyticsEvent } from '../hooks/useAnalytics'
import { NetworkRequest } from '../hooks/useNetwork'
import { ProductResponse, useProduct } from '../hooks/useProducts'
import { useScreenRefreshControl } from '../hooks/useScreenRefreshControl'
import { useScreenTimeInterval } from '../hooks/useScreenTimeInterval'
import { getTracksWithAllDsp, periodToPeriodChangePercentage } from '../streams'
import { defaultTimeInterval, TimeInterval } from '../types/TimeInterval'
import { trackItemFieldsFromTrack } from '../types/graphqlCompatibilityHelpers'
import { isProductExplicit, timeRangeInterval, trackMatchesDsp } from '../util'
import { hasStreams } from './tabs/TrackListStreamsTab'

export const ProductDetailScreen: React.FC<
  ReactNavigationProps<ScreenNames.ProductDetail>
> = ({ navigation, route }) => {
  const screenName = 'Product Detail Screen'
  const artist = useContext(ArtistContext)

  const [timeInterval, setTimeInterval] = useScreenTimeInterval(
    route.params.time_interval ?? defaultTimeInterval,
    {
      screenName,
      artistName: artist.name,
      entityId: artist.sonyArtistId,
    }
  )

  const interval = timeRangeInterval(timeInterval)
  const productId = route.params.product_id

  const response = useProduct(productId, interval)
  const onPullToRefresh = () => {
    sendAnalyticsEvent(EventType.PULL_TO_REFRESH, {
      artist_selected: artist.name,
      timeframe_selected: timeInterval,
      page: screenName,
      subject: 'user',
      verb: 'refreshed',
      object: 'product',
    })
    response.retry()
  }
  const { refreshControl } = useScreenRefreshControl(
    onPullToRefresh,
    response.refreshing
  )

  return (
    <CommonScreenContainer screenName={screenName}>
      <ErrorBoundary error={response.error} refreshControl={refreshControl}>
        <Content
          productId={productId}
          {...response}
          navigation={navigation}
          timeInterval={timeInterval}
          setTimeInterval={setTimeInterval}
          refreshControl={refreshControl}
        />
      </ErrorBoundary>
    </CommonScreenContainer>
  )
}

function Content({
  productId,
  navigation,
  data,
  refreshControl,
  showToast,
  timeInterval,
  setTimeInterval,
}: {
  productId: string
  navigation: ReactNavigationProps<ScreenNames.ProductDetail>['navigation']
  timeInterval: TimeInterval
  setTimeInterval: (timeInterval: TimeInterval) => void
  refreshControl: React.ReactElement<RefreshControlProps>
} & NetworkRequest<ProductResponse>) {
  const tracks = data
    ? getTracksWithAllDsp(data.streams)
        .flatMap(trackMatchesDsp('all'))
        .filter(hasStreams)
        .map(({ item, data }) => ({
          track: item,
          currentPeriodStreams: data.currentPeriod,
          changePercentage: periodToPeriodChangePercentage(data) ?? undefined,
        }))
    : null

  return (
    <>
      <HeaderNav
        title={data?.product?.name ?? ' '}
        titleSecondary={data?.product?.digitalTitleSuppl ?? ' '}
        showToast={showToast}
        navigation={navigation}
        style={{
          zIndex: 10,
        }}
        timeInterval={timeInterval}
        setTimeInterval={setTimeInterval}
      />
      {data?.product != null && data?.streams != null ? (
        <ProductDetailHeading
          product={data.product}
          isExplicit={isProductExplicit(data.product)}
          onPressCompare={() => {
            navigation.navigate(ScreenNames.ProductTracksComparison, {
              product_id: productId,
            })
          }}
          disableCompare={!tracks || tracks.length === 0}
        />
      ) : null}
      {tracks != null ? (
        <TrackList
          refreshControl={refreshControl}
          renderTrack={(track, i) => (
            <StreamsListItem
              key={track.track.isrc}
              track={trackItemFieldsFromTrack(track.track)}
              index={i}
              currentPeriodStreams={track.currentPeriodStreams}
              changePercentage={track.changePercentage}
              onPress={() =>
                navigation.navigate(ScreenNames.Track, {
                  isrc: track.track.isrc,
                })
              }
            />
          )}
          tracks={tracks}
          style={{
            paddingHorizontal: 4,
          }}
        />
      ) : (
        <TrackListSkeleton numItems={4} dspFilter />
      )}
    </>
  )
}
