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

import { ReactNavigationProps } from '../Navigation'
import { Styles } from '../Styles'
import { CommonScreenContainer } from '../components/CommonScreenContainer'
import { Countries } from '../components/Countries'
import { ErrorBoundary } from '../components/ErrorBoundary'
import { HeaderNav } from '../components/HeaderNav'
import { useGet } from '../components/Network'
import { SearchBar } from '../components/SearchBar'
import { DemographicCountrySkeleton } from '../components/Skeleton'
import { ScreenNames } from '../constants/ScreenNames'
import { ArtistContext } from '../contexts/ArtistContext'
import { UserContext } from '../contexts/UserContext'
import { EventType, sendAnalyticsEvent } from '../hooks/useAnalytics'
import { CountriesData } from '../hooks/useCountryStreams'
import { useNetwork, NetworkRequest } from '../hooks/useNetwork'
import { useScreenRefreshControl } from '../hooks/useScreenRefreshControl'
import { useScreenTimeInterval } from '../hooks/useScreenTimeInterval'
import { Strings } from '../i18n'
import { CountryWithStreams } from '../types/Country'
import { defaultTimeInterval } from '../types/TimeInterval'
import { timeRangeDates } from '../util'

export const CountriesScreen: React.FC<
  ReactNavigationProps<ScreenNames.Countries>
> = ({ navigation, route }) => {
  const screenName = 'Countries Screen'
  const user = useContext(UserContext)
  const artist = useContext(ArtistContext)

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

  const [filter, setFilter] = useState('')
  const { startDate, endDate } = timeRangeDates(timeInterval)

  const response = useNetwork<CountriesData>(
    useGet(
      `screens/artist/${artist.sonyArtistId}/countries?startDate=${startDate}&endDate=${endDate}`,
      user
    )
  )
  const onPullToRefresh = () => {
    sendAnalyticsEvent(EventType.PULL_TO_REFRESH, {
      artist_selected: artist.name,
      timeframe_selected: timeInterval,
      page: screenName,
      subject: 'user',
      verb: 'refreshed',
      object: 'countries',
    })
    response.retry()
  }
  const { refreshControl } = useScreenRefreshControl(
    onPullToRefresh,
    response.refreshing
  )

  return (
    <CommonScreenContainer screenName={screenName}>
      <HeaderNav
        title={Strings.Shared.Countries}
        navigation={navigation}
        showToast={response.showToast}
        style={{
          zIndex: 10,
        }}
        timeInterval={timeInterval}
        setTimeInterval={setTimeInterval}
      />
      <View
        style={{
          flex: 1,
          ...Styles.screenHorizontalPadding,
        }}
      >
        <SearchBar
          filter={filter}
          setFilter={setFilter}
          placeholder={Strings.Shared.SearchHintMarket}
        />
        <ErrorBoundary error={response.error} refreshControl={refreshControl}>
          <Content
            {...response}
            refreshControl={refreshControl}
            navigation={navigation}
            filter={filter}
            artistId={artist.sonyArtistId}
          />
        </ErrorBoundary>
      </View>
    </CommonScreenContainer>
  )
}

type Filter = {
  filter: string
}
function Content({
  navigation,
  data,
  refreshControl,
  filter,
  artistId,
}: {
  navigation: ReactNavigationProps<ScreenNames.Globe>['navigation']
  artistId: string
} & NetworkRequest<CountriesData> &
  Filter & { refreshControl: React.ReactElement<RefreshControlProps> }) {
  const countries = data?.countries
    .sort(byStreams)
    .map((country, index) => ({ ...country, position: index + 1 }))
    .filter(countryMatchesFilter(filter))

  return countries ? (
    <Countries
      countries={countries}
      onPressCountry={(country) => {
        navigation.navigate(ScreenNames.Market, {
          market: country.countryCode,
          artist_id: artistId,
        })
      }}
      refreshControl={refreshControl}
    />
  ) : (
    <DemographicCountrySkeleton numItems={5} />
  )
}

function countryMatchesFilter(filter: string) {
  const normalizedFilter = filter.toLowerCase().trim()
  return ({ item: country }: CountryWithStreams) =>
    country.name.toLowerCase().includes(normalizedFilter)
}

function byStreams(a: CountryWithStreams, b: CountryWithStreams) {
  return b.data.current - a.data.current
}
