import _ from 'lodash'
import React from 'react'
import { RefreshControlProps } from 'react-native'

import { ErrorBoundary } from '../../components/ErrorBoundary'
import { Filters, streamingDspFilters } from '../../components/Filters'
import { TrackListSkeleton } from '../../components/Skeleton'
import { TrackList, TrackListItem } from '../../components/TrackList'
import { Item } from '../../components/listitems/StreamsListItem'
import { NetworkError } from '../../hooks/useNetwork'
import { periodToPeriodChangePercentage } from '../../streams'
import { Track } from '../../types/Track'
import { trackItemFieldsFromTrack } from '../../types/graphqlCompatibilityHelpers'
import { TrackWithStreamsByDspAndDate, Dsp } from '../../types/types'
import { trackMatchesDsp, TrackStreams } from '../../util'

export type GetTracksFn = (tracks: TrackListItem[]) => TrackListItem[]

export function hasStreams(track: TrackStreams): track is {
  item: Track
  data: {
    dsp: string
    currentPeriod: number
    currentPeriodByDay?: (number | null)[]
  }
} {
  return track.data.currentPeriod != null
}

export const TrackListStreamsTab: React.FC<{
  tracks?: TrackWithStreamsByDspAndDate[]
  limit?: number
  onLoad: (dsp: Dsp) => void
  refreshControl: React.ReactElement<RefreshControlProps>
  error: NetworkError | null
  onPressTrack: (isrc: string) => void
  beforeList?: React.ReactNode
  getTracks: GetTracksFn
  displayRank?: boolean
  showDspSelector?: boolean
  ListItem: React.FC<Item>
}> = ({
  tracks,
  onLoad,
  limit,
  refreshControl,
  error,
  onPressTrack,
  beforeList,
  getTracks,
  displayRank,
  showDspSelector,
  ListItem,
}) => (
  <ErrorBoundary error={error} refreshControl={refreshControl}>
    {tracks ? (
      <Filters
        filters={streamingDspFilters}
        selectedFilter="all"
        onLoad={onLoad}
        showSelector={showDspSelector}
      >
        {(dsp) => (
          <React.Fragment key={dsp}>
            {beforeList}
            <TrackList
              refreshControl={refreshControl}
              renderTrack={(track, i) => (
                <ListItem
                  index={displayRank === false ? undefined : i}
                  track={trackItemFieldsFromTrack(track.track)}
                  currentPeriodStreams={track.currentPeriodStreams}
                  changePercentage={track.changePercentage}
                  onPress={() => onPressTrack(track.track.isrc)}
                />
              )}
              tracks={
                //TODO: Remove uniqueness filtering once uniqueness is enforced upstream
                _.uniqBy(
                  getTracks(
                    tracks
                      .flatMap(trackMatchesDsp(dsp))
                      .filter(hasStreams)
                      .map(({ item, data }) => ({
                        track: item,
                        currentPeriodStreams: data.currentPeriod,
                        changePercentage:
                          periodToPeriodChangePercentage(data) ?? undefined,
                      }))
                  ),
                  (t) => t.track.isrc
                ).slice(0, limit)
              }
            />
          </React.Fragment>
        )}
      </Filters>
    ) : (
      <TrackListSkeleton numItems={4} dspFilter />
    )}
  </ErrorBoundary>
)

TrackListStreamsTab.defaultProps = { getTracks: (x) => x }
