import { Interval } from 'date-fns'
import React, { useContext } from 'react'
import { Animated, Text, TouchableOpacity, View } from 'react-native'

import { colors, DspColors } from '../Colors'
import {
  SocialMedia,
  socialMedias,
  StreamingDsp,
  streamingDsps,
} from '../Consts'
import { ReactNavigationProps } from '../Navigation'
import { EntityScreenStyles, TextStyles } from '../Styles'
import { ArtistHeader } from '../components/ArtistHeader'
import { ArtistStreamsDemographicsCarousel } from '../components/ArtistStreamsDemographicsCarousel'
import { AutoLayout } from '../components/AutoLayout'
import { Button } from '../components/Button'
import { Carousel } from '../components/Carousel'
import { CommonScreenContainer } from '../components/CommonScreenContainer'
import { DataTile } from '../components/DataTile'
import { EntityStreamsTile } from '../components/EntityStreamsTile'
import { SocialTile } from '../components/SocialTile'
import {
  TrackComparisonSelectionModalContainer,
  useTrackComparisonSelectionModal,
} from '../components/TrackComparisonSelectionModal'
import { SimpleCountryRow } from '../components/TrackTopStreamingCountriesTile'
import { isSocialMedia, SocialData, useSocial } from '../components/useSocial'
import { ScreenNames } from '../constants/ScreenNames'
import { ArtistContext } from '../contexts/ArtistContext'
import { EventType, sendAnalyticsEvent } from '../hooks/useAnalytics'
import { useArtistStreams } from '../hooks/useArtistStreams'
import { useCountryStreams } from '../hooks/useCountryStreams'
import { Strings } from '../i18n'
import { TrackComparison as TrackComparisonIllustration } from '../illustrations/TrackComparison'
import { Artist } from '../types/Artist'
import { defaultTimeInterval, TimeInterval } from '../types/TimeInterval'
import { timeRangeInterval } from '../util'
import { formatInterval } from '../util/date'
import { carouselStyleProps, styles } from './TrackScreenV2'

const screenName = 'Artist Screen'

export const ArtistScreen: React.FC<
  ReactNavigationProps<ScreenNames.Artist>
> = ({ navigation }) => {
  const artist = useContext(ArtistContext)
  const timeInterval = defaultTimeInterval

  const sendAnalyticsForSwipe =
    (carousel: string) => (dsp: StreamingDsp | 'all') => {
      sendAnalyticsEvent(EventType.ARTIST_SCREEN_CAROUSEL_SWIPED, {
        carousel,
        screen: 'Artist Screen',
        dsp,
        artist: {
          name: artist.name,
          sonyArtistId: artist.sonyArtistId,
        },
        subject: 'user',
        verb: 'swiped',
        object: 'carousel',
      })
    }

  return (
    <CommonScreenContainer screenName={screenName}>
      <ArtistHeader
        onPressSearchButton={() => navigation.navigate(ScreenNames.Search)}
        timeInterval={timeInterval}
      />
      <Animated.ScrollView
        showsVerticalScrollIndicator={false}
        contentContainerStyle={{ flexGrow: 1 }}
      >
        <View style={EntityScreenStyles.container}>
          <View style={{ marginVertical: 16 }}>
            <View style={{ marginBottom: 24 }}>
              <TrackComparison />
            </View>

            <AllStreamsCarousel
              timeInterval={timeInterval}
              onSwipe={sendAnalyticsForSwipe('Streams')}
              onPressItem={(item: StreamingDsp | 'all') =>
                navigation.navigate(ScreenNames.ArtistStreamsGraph, {
                  dsp: item,
                })
              }
            />

            <SocialsCarousel
              timeInterval={timeInterval}
              onPressItem={(item) =>
                navigation.navigate(ScreenNames.Followers, {
                  dsp_slug: item.dspSlug,
                  time_interval: timeInterval,
                })
              }
            />

            <TopMarketCarousel
              artist={artist}
              timeInterval={timeInterval}
              onPressItem={(countryCode) => {
                navigation.navigate(ScreenNames.Market, {
                  artist_id: artist.sonyArtistId,
                  market: countryCode,
                })
              }}
              onPressTitle={() =>
                navigation.navigate(ScreenNames.Countries, {
                  artist_id: artist.sonyArtistId,
                  time_interval: timeInterval,
                })
              }
            />
            <ArtistStreamsDemographicsCarousel
              timeInterval={timeInterval}
              countryCode="worldwide"
              onSwipe={() => {}}
            />
          </View>
        </View>
      </Animated.ScrollView>
    </CommonScreenContainer>
  )
}

const TrackComparison: React.FC = () => {
  const {
    trackComparisonSelectionModalOpen,
    setTrackComparisonSelectionModalOpen,
  } = useTrackComparisonSelectionModal()
  const artist = useContext(ArtistContext)

  const sendTrackComparisonSelectedAnalyticsEvent = () => {
    sendAnalyticsEvent(EventType.TRACK_COMPARISON_OPENED, {
      screen: screenName,
      artist: {
        name: artist.name,
        sonyArtistId: artist.sonyArtistId,
      },
      subject: 'user',
      verb: 'opened',
      object: 'track_comparison',
    })
  }

  return (
    <>
      <View style={{ flex: 1 }}>
        <View
          style={{
            flexDirection: 'row',
            justifyContent: 'space-between',
            marginVertical: 16,
          }}
        >
          <Text style={[TextStyles.body, { color: colors.white }]}>
            {Strings.TrackComparison.TrackComparison}
          </Text>
        </View>
        <View
          style={{
            flex: 1,
            flexDirection: 'row',
            justifyContent: 'space-between',
            marginHorizontal: -4,
          }}
        >
          <TrackComparisonTile
            onPress={() => {
              setTrackComparisonSelectionModalOpen(true)
              sendTrackComparisonSelectedAnalyticsEvent()
            }}
          />
        </View>
      </View>
      {trackComparisonSelectionModalOpen && (
        <TrackComparisonSelectionModalContainer
          open={trackComparisonSelectionModalOpen}
          onClose={() => setTrackComparisonSelectionModalOpen(false)}
        />
      )}
    </>
  )
}

const TrackComparisonTile: React.FC<{
  onPress: () => void
}> = ({ onPress }) => (
  <View
    style={{
      flexDirection: 'row',
      flex: 1,
      height: 168,
      backgroundColor: colors.metals.metal2,
      margin: 4,
      padding: 24,
      borderRadius: 8,
    }}
  >
    <View
      style={{
        flex: 1,
        justifyContent: 'space-around',
        marginRight: 16,
      }}
    >
      <Text
        style={{
          ...TextStyles.bodySmall,
          color: colors.midWhite,
          marginBottom: 28,
        }}
      >
        {Strings.TrackComparison.SelectUpToCompare}
      </Text>
      <Button onPress={onPress}>{Strings.Shared.Compare}</Button>
    </View>
    <View
      style={{
        flex: 1,
        alignItems: 'flex-end',
        marginLeft: 16,
      }}
    >
      <TrackComparisonIllustration />
    </View>
  </View>
)

const TopMarketCarousel: React.FC<{
  artist: Artist
  timeInterval: TimeInterval
  onPressItem: (countryCode: string) => void
  onPressTitle: () => void
}> = ({ artist, onPressItem, onPressTitle, timeInterval }) => {
  const result = useCountryStreams(artist.sonyArtistId, timeInterval)
  const topCountries = result.data?.countries
    .sort((a, b) => (a.data.current > b.data.current ? -1 : 0))
    .slice(0, 8)

  return (
    <Carousel<StreamingDsp | 'all'>
      items={['all']}
      style={styles.carousel}
      renderItem={({ item }) => (
        <DataTile
          key={item}
          dsp={item}
          title={Strings.Shared.TopStreamingMarkets}
          subTitle={formatInterval(timeRangeInterval(timeInterval))}
          titleWidget={
            <TouchableOpacity
              onPress={onPressTitle}
              style={{ alignSelf: 'center' }}
            >
              <Text style={[TextStyles.body]}>{Strings.Shared.ViewAll}</Text>
            </TouchableOpacity>
          }
          style={[
            {
              flex: 1,
              // Remove excess padding for tile that doesn't have background
              paddingTop: 8,
              backgroundColor: 'transparent',
            },
          ]}
          error={result.error}
        >
          {topCountries ? (
            <AutoLayout gap={16}>
              {topCountries.map((country, index) => {
                const lastItem = index === topCountries.length - 1
                const bottomBorder = {
                  paddingBottom: 12,
                  borderColor: colors.metals.metal0,
                  borderBottomWidth: 1,
                }
                return (
                  <View
                    key={country.item.countryCode}
                    style={lastItem ? {} : bottomBorder}
                  >
                    <TouchableOpacity
                      onPress={() => onPressItem(country.item.countryCode)}
                      accessibilityLabel={country.item.countryCode}
                    >
                      <SimpleCountryRow
                        countryCode={country.item.countryCode}
                        changePercentage={
                          ((country.data.current - country.data.previous) /
                            country.data.previous) *
                          100
                        }
                        streamCount={country.data.current}
                      />
                    </TouchableOpacity>
                  </View>
                )
              })}
            </AutoLayout>
          ) : null}
        </DataTile>
      )}
    />
  )
}

type Socials = SocialData<SocialMedia>
const SocialsCarousel: React.FC<{
  timeInterval: TimeInterval
  onPressItem: (item: Socials) => void
  onSwipe?: (item: Socials) => void
}> = ({ timeInterval, onPressItem, onSwipe }) => {
  const { data: followers, error } = useSocial(timeInterval)

  const socials =
    followers
      ?.filter(isSocialMedia)
      .sort(
        (a, b) =>
          socialMedias.indexOf(a.dspSlug) - socialMedias.indexOf(b.dspSlug)
      ) ?? []

  return (
    <Carousel<Socials>
      items={socials}
      renderItem={({ item }) => (
        <SocialTile
          dsp={item.dspSlug}
          key={item.dspSlug}
          profile={item.profile}
          data={{ yValues: item.data, strokeColor: DspColors[item.dspSlug] }}
          current={item.current}
          previous={item.previous}
          timeInterval={timeInterval}
          onPress={() => onPressItem(item)}
          title={item.title}
          style={styles.tile}
          error={error}
        />
      )}
      onSwipe={onSwipe}
      {...carouselStyleProps}
    />
  )
}

const AllStreamsCarousel: React.FC<{
  timeInterval: TimeInterval
  onPressItem: (item: StreamingDsp | 'all') => void
  onSwipe: (item: StreamingDsp | 'all') => void
}> = ({ timeInterval, onPressItem, onSwipe }) => (
  <Carousel<StreamingDsp | 'all'>
    items={['all', ...streamingDsps]}
    renderItem={({ item }) => {
      const useEntityStreams = (interval: Interval) =>
        useArtistStreams(interval, item, 'worldwide')
      return (
        <EntityStreamsTile
          key={item}
          dsp={item}
          timeInterval={timeInterval}
          onPress={() => onPressItem(item)}
          useEntityStreams={useEntityStreams}
          title={Strings.Shared.ArtistStreams}
          style={styles.tile}
          strokeColor={DspColors[item]}
        />
      )
    }}
    onSwipe={onSwipe}
    style={styles.carousel}
    indicatorStyle={styles.carouselIndicator}
  />
)
