import { chunk } from 'lodash'
import { useContext } from 'react'

import { StreamingDsp, streamingDsps } from '../Consts'
import { DateData } from '../DateData'
import { ArtistContext } from '../contexts/ArtistContext'
import { GraphQLContext } from '../contexts/GraphQLContext'
import { TrackDspId, TrackMetricQuery } from '../graphql/__generated__/sdk'
import { streamsSummary } from '../streams'
import { TimeInterval } from '../types/TimeInterval'
import { timeRangeInterval } from '../util'
import {
  intervalToStrings,
  previousInterval as getPreviousInterval,
} from '../util/date'
import { IntervalSummary } from './useEntityStreams'
import { NetworkError, useNetwork } from './useNetwork'

export interface TrackStreamsResponse {
  streams?: DateData<number | null>[][]
  error: NetworkError | null
}

export function useTrackStreams(
  isrc: string,
  queries: TrackMetricQuery[]
): TrackStreamsResponse {
  const g = useContext(GraphQLContext)
  const artist = useContext(ArtistContext)

  const variables = {
    artistId: artist.sonyArtistId,
    isrc,
    intervalMetricQueries: queries,
  }

  const cacheKey = queries
    .map((query) => {
      return `${query.dspId}/${query.interval.end}/${query.interval.start}/${query.market}`
    })
    .join('_')

  const response = g.useGetTrackStreamMetrics(
    `trackStreams/${isrc}/${cacheKey}`,
    variables,
    {
      shouldRetryOnError: false,
    }
  )

  const track = response?.data?.artist?.track

  return {
    streams: track?.metrics.map((metric) =>
      metric.map(({ date, streams }) => ({
        date,
        data: streams,
      }))
    ),
    error: useNetwork(response).error,
  }
}

export const generateStreamQueriesWithTimeInterval = (
  dsp: StreamingDsp | 'all',
  market: string,
  timeInterval: TimeInterval
) => generateStreamQueries(dsp, market, timeRangeInterval(timeInterval))

export const generateStreamQueries = (
  dsp: StreamingDsp | 'all',
  market: string,
  interval: Interval
): TrackMetricQuery[][] => {
  const currentInterval = interval
  const previousInterval = getPreviousInterval(currentInterval)

  const dsps = dsp === 'all' ? [null, ...streamingDsps] : [dsp]

  return dsps.map((dsp) =>
    [currentInterval, previousInterval].map((interval) => ({
      market,
      interval: intervalToStrings(interval),
      dspId: dsp as TrackDspId,
    }))
  )
}

export function mapToSummaries(
  response: TrackStreamsResponse,
  dsps: StreamingDsp[]
): IntervalSummary[] {
  return chunk(response.streams, 2).map(([current, previous], index) => ({
    ...streamsSummary(current, previous),
    dsp: dsps[index],
  }))
}
