import React, { useState } from 'react'
import {
  View,
  StyleSheet,
  Animated,
  useWindowDimensions,
  Text,
  ScrollView,
  ActivityIndicator,
} from 'react-native'

import { colors, colorsV2, DspColors } from '../Colors'
import { TextStyles, Styles } from '../Styles'

import { Filters } from '../components/Filters'
import { HeaderNav } from '../components/HeaderNav'
import {
  useSocial,
  DSPS,
  SocialData,
  isSocialMedia,
} from '../components/useSocial'
import { SocialIcon } from '../components/SocialIcon'
import { NetworkRequest } from '../components/useNetwork'
import { ErrorBoundary } from '../components/ErrorBoundary'

import { CommonScreenContainer } from '../components/CommonScreenContainer'
import { Graph } from '../components/Graph'
import { Number } from '../components/Number'
import { GraphDateLabels } from '../components/GraphDateLabels'
import {
  daysInTimeRange,
  formatCount,
  labelsForInterval,
  timeRangeDates,
} from '../util'

import { useAnimatedChart } from '../hooks/useAnimatedChart'
import { ReactNavigationProps } from '../Navigation'
import { ScreenNames } from '../constants/ScreenNames'
import { EventType, useAnalytics } from '../hooks/useAnalytics'
import _ from 'lodash'
import { ChangePlusMinusAndNumber } from '../components/ChangePlusMinusAndNumber'
import { SocialMedia, socialMedias } from '../Consts'
import { BarLabel } from '../types/types'
import { defaultTimeInterval, TimeInterval } from '../types/TimeInterval'

export const styles = StyleSheet.create({
  container: {
    flexGrow: 1,
  },
  social: {
    flexGrow: 1,
    marginVertical: 16,
  },
  followers: {
    flexGrow: 1,
    alignContent: 'flex-end',
  },
  graphContainer: {
    flexGrow: 1,
  },
  labelContainer: {
    paddingTop: 8,
  },
  changeNumber: {
    ...TextStyles.h3,
  },
  arrowContainer: {
    paddingHorizontal: 10,
  },
  socialTop: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingHorizontal: 10,
  },
  numberContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  label: {
    ...TextStyles.tiny,
  },
})

const padding = Styles.screenHorizontalPadding.paddingHorizontal

const FollowersLabel = ({
  selection,
  labels,
  row,
}: {
  selection?: number
  labels?: BarLabel[]
  row?: SocialData
}) => {
  const label = selection != null && labels != null ? labels[selection] : null
  const rowData =
    selection != null && row != null ? row.data?.[selection] : null
  return (
    <View style={styles.labelContainer}>
      <View style={{ marginLeft: 8 }}>
        <Text style={[styles.label, { color: colors.gray }]}>
          {label?.weekday ?? ' '}
        </Text>
        <Text style={[styles.label, { color: colors.gray }]}>
          {label?.date ?? ' '}
        </Text>
        <Text style={[styles.label, TextStyles.body, { color: colors.white }]}>
          {rowData ? formatCount(rowData) : ' '}
        </Text>
      </View>
    </View>
  )
}

export const FollowersScreen: React.FC<
  ReactNavigationProps<ScreenNames.Followers>
> = ({ navigation, route }) => {
  const initialDspSlug = route.params.dspSlug
  const [timeInterval, setTimeInterval] = useState<TimeInterval>(
    route.params.timeInterval ?? defaultTimeInterval
  )
  const { data, ...request } = useSocial('Followers Screen', timeInterval)
  const socialData = data?.filter(isSocialMedia)

  return (
    <CommonScreenContainer>
      <View
        style={{
          flex: 1,
          backgroundColor: colors.darkGray,
        }}
      >
        <HeaderNav
          title="Social"
          navigation={navigation}
          showToast={request.showToast}
          style={{
            backgroundColor: colorsV2.black,
          }}
          titleStyle={{
            textTransform: 'capitalize',
          }}
          timeInterval={timeInterval}
          setTimeInterval={setTimeInterval}
        />
        <View style={{ flex: 1, ...Styles.screenHorizontalPadding }}>
          <ErrorBoundary
            error={request.error}
            refreshControl={request.refreshControl}
          >
            <Content
              {...{ navigation, route }}
              {...request}
              data={socialData}
              initialDspSlug={initialDspSlug}
              timeInterval={timeInterval}
            />
          </ErrorBoundary>
        </View>
      </View>
    </CommonScreenContainer>
  )
}

const Content: React.FC<
  NetworkRequest<SocialData[]> & {
    initialDspSlug: SocialMedia
    timeInterval: TimeInterval
  }
> = ({ initialDspSlug, data, refreshControl, timeInterval }) => {
  const windowWidth = useWindowDimensions().width
  const width = windowWidth - padding * 2
  const days = daysInTimeRange(timeInterval)
  const { startDate, endDate } = timeRangeDates(timeInterval)
  const labels = labelsForInterval(startDate, endDate)
  const [scrolling, setScrolling] = useState<boolean>(false)
  const { selection, viewProps } = useAnimatedChart(days, width, scrolling)

  const dataForDsp = (data: SocialData[], dsp: string) =>
    data.find(({ dspSlug }) => dspSlug === dsp)

  return data != null ? (
    <ScrollView
      contentContainerStyle={styles.container}
      refreshControl={refreshControl}
      scrollEnabled={selection == null}
      onScrollBeginDrag={() => void setScrolling(true)}
      onScrollEndDrag={() => void setScrolling(false)}
    >
      <View style={styles.social}>
        <Filters<SocialMedia>
          selectedFilter={initialDspSlug}
          filters={Object.values(socialMedias).map((key) => ({
            key,
            label: key,
            disabled: dataForDsp(data, key)?.current == null,
          }))}
          onLoad={(socialMedia) =>
            useAnalytics(
              EventType.SOCIAL_MEDIA_DETAILS_VIEWED,
              {
                social_media_type: socialMedia,
                subject: 'user',
                verb: 'viewed',
                object: 'social_media',
              },
              true,
              timeInterval
            )
          }
        >
          {(dsp) => {
            const row = dataForDsp(data, dsp)

            if (row == null) {
              return null
            }

            const { current, previous } = row
            const textStyle = _.omit(styles.changeNumber, 'color')
            const changeNumber =
              current === null || previous === null
                ? undefined
                : current - previous

            return (
              <View key={dsp} style={styles.followers}>
                <SocialIcon dspSlug={dsp} />
                <Text
                  style={{
                    ...TextStyles.body,
                    textTransform: 'capitalize',
                  }}
                >
                  {fullTitle(dsp)}
                </Text>
                <View style={styles.numberContainer}>
                  {current ? (
                    <Number number={current} style={textStyle} />
                  ) : null}
                  <ChangePlusMinusAndNumber
                    changeNumber={changeNumber}
                    textStyle={textStyle}
                  />
                </View>
                <FollowersLabel
                  {...{
                    selection,
                    labels,
                    row,
                  }}
                />
                <Animated.View style={styles.graphContainer} {...viewProps}>
                  <Graph
                    data={[
                      {
                        yValues: row.data,
                        strokeColor: DspColors[dsp],
                      },
                    ]}
                    strokeWidth={4}
                    selection={selection}
                  />
                </Animated.View>
                <GraphDateLabels startDate={startDate} endDate={endDate} />
              </View>
            )
          }}
        </Filters>
      </View>
    </ScrollView>
  ) : (
    <ActivityIndicator style={{ flex: 1 }} size="large" />
  )
}

function fullTitle(dsp: string) {
  return DSPS.find(({ slug }) => slug === dsp)?.title ?? 'followers'
}
