import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import { RouteProp } from '@react-navigation/native'
import {
  createStackNavigator,
  StackNavigationProp,
} from '@react-navigation/stack'
import React, { useContext } from 'react'
import { ActivityIndicator } from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'

import { colors } from './Colors'
import {
  ChartDsp,
  Dsp,
  PlaylistDsp,
  SocialMedia,
  StreamingDsp,
  VideoDsp,
} from './Consts'
import { ScreenNames } from './constants/ScreenNames'
import { ArtistContext } from './contexts/ArtistContext'
import { UserContext } from './contexts/UserContext'
import Dashboard from './icons/Dashboard'
import Globe from './icons/Globe'
import Library from './icons/Library'
import SettingsIcon from './icons/Settings'
import { ArtistScreen } from './screens/ArtistScreen'
import { ArtistStreamsGraphScreen } from './screens/ArtistStreamsGraphScreen'
import { CountriesScreen } from './screens/CountriesScreen'
import { DeveloperScreen } from './screens/DeveloperScreen'
import { FollowersScreen } from './screens/FollowersScreen'
import { LibraryScreen } from './screens/LibraryScreen'
import { LoginScreen } from './screens/LoginScreen'
import { MarketChartsScreen } from './screens/MarketChartsScreen'
import { MarketScreen } from './screens/MarketScreen'
import { MarketSelectorScreen } from './screens/MarketSelectorScreen'
import { ProductDetailScreen } from './screens/ProductDetailScreen'
import { ProductTracksComparisonScreen } from './screens/ProductTracksComparisonScreen'
import { ProductsScreen } from './screens/ProductsScreen'
import { SearchScreen } from './screens/SearchScreen'
import { SettingsScreen } from './screens/SettingsScreen'
import { TrackChartsScreen } from './screens/TrackChartsScreen'
import { TrackListScreen, TrackListScreenMode } from './screens/TrackListScreen'
import { TrackPlaylistScreen } from './screens/TrackPlaylistScreen'
import { TrackPlaylistsScreen } from './screens/TrackPlaylistsScreen'
import { TrackScreen } from './screens/TrackScreenV2'
import { TrackStreamSourcesScreen } from './screens/TrackStreamSourcesScreen'
import { TrackStreamsGraphScreen } from './screens/TrackStreamsGraphScreen'
import { TrackTikTokScreen } from './screens/TrackTikTokScreen'
import { TracksComparisonScreen } from './screens/TracksComparisonScreen'
import { TracksScreen } from './screens/TracksScreen'
import { VideoEngagementGraphScreen } from './screens/VideoEngagementGraphScreen'
import { VideoScreen } from './screens/VideoScreen'
import { VideoViewSourcesScreen } from './screens/VideoViewSourcesScreen'
import { VideoViewsGraphScreen } from './screens/VideoViewsGraphScreen'
import { VideosScreen, VideosScreenMode } from './screens/VideosScreen'
import { TimeInterval } from './types/TimeInterval'
import { Track } from './types/Track'
import { Mode } from './types/helpers'

const trackScreens = [
  {
    name: ScreenNames.Track,
    component: TrackScreen,
  },
  {
    name: ScreenNames.TrackStreamSources,
    component: TrackStreamSourcesScreen,
  },
  {
    name: ScreenNames.TrackStreamsGraph,
    component: TrackStreamsGraphScreen,
  },
  {
    name: ScreenNames.TrackCharts,
    component: TrackChartsScreen,
  },
  {
    name: ScreenNames.TrackPlaylists,
    component: TrackPlaylistsScreen,
  },
  {
    name: ScreenNames.TrackTikTok,
    component: TrackTikTokScreen,
  },

  {
    name: ScreenNames.TrackPlaylist,
    component: TrackPlaylistScreen,
  },
  {
    name: ScreenNames.MarketSelector,
    component: MarketSelectorScreen,
  },
  {
    name: ScreenNames.ProductTracksComparison,
    component: ProductTracksComparisonScreen,
  },
  {
    name: ScreenNames.TracksComparison,
    component: TracksComparisonScreen,
  },
]

const Login = createStackNavigator()
export const LoginNavigation = () => (
  <Login.Navigator headerMode="none" initialRouteName={ScreenNames.Login}>
    <Settings.Screen name={ScreenNames.Login} component={LoginScreen} />
    <Settings.Screen name={ScreenNames.Developer} component={DeveloperScreen} />
  </Login.Navigator>
)

const Country = createStackNavigator()
const CountryNavigation = () => (
  <Country.Navigator headerMode="none">
    <Country.Screen name={ScreenNames.Countries} component={CountriesScreen} />
    <Country.Screen name={ScreenNames.Market} component={MarketScreen} />
    <Country.Screen
      name={ScreenNames.ArtistStreamsGraph}
      component={ArtistStreamsGraphScreen}
    />
    <Country.Screen
      name={ScreenNames.MarketCharts}
      component={MarketChartsScreen}
    />
    {trackScreens.map(({ name, component }) => (
      <Country.Screen key={name} name={name} component={component} />
    ))}
  </Country.Navigator>
)

const Tracks = createStackNavigator()
const TracksNavigation = () => (
  <Tracks.Navigator headerMode="none">
    <Tracks.Screen name={ScreenNames.Library} component={LibraryScreen} />
    <Tracks.Screen name={ScreenNames.Tracks} component={TracksScreen} />
    <Tracks.Screen name={ScreenNames.TrackList} component={TrackListScreen} />
    {trackScreens.map(({ name, component }) => (
      <Tracks.Screen key={name} name={name} component={component} />
    ))}
    <Tracks.Screen name={ScreenNames.Products} component={ProductsScreen} />
    <Tracks.Screen
      name={ScreenNames.ProductDetail}
      component={ProductDetailScreen}
    />
    <Tracks.Screen name={ScreenNames.Videos} component={VideosScreen} />
    <Tracks.Screen name={ScreenNames.Video} component={VideoScreen} />
    <Tracks.Screen
      name={ScreenNames.VideoViewsGraph}
      component={VideoViewsGraphScreen}
    />
    <Tracks.Screen
      name={ScreenNames.VideoViewSources}
      component={VideoViewSourcesScreen}
    />
    <Tracks.Screen
      name={ScreenNames.VideoEngagementGraph}
      component={VideoEngagementGraphScreen}
    />
    <Tracks.Screen name={ScreenNames.Search} component={SearchScreen} />
  </Tracks.Navigator>
)

const Artist = createStackNavigator()
const ArtistNavigation = () => (
  <Artist.Navigator headerMode="none">
    <Artist.Screen name={ScreenNames.Artist} component={ArtistScreen} />
    <Artist.Screen name={ScreenNames.Followers} component={FollowersScreen} />
    <Artist.Screen
      name={ScreenNames.ArtistStreamsGraph}
      component={ArtistStreamsGraphScreen}
    />
    <Artist.Screen name={ScreenNames.Search} component={SearchScreen} />
    {trackScreens.map(({ name, component }) => (
      <Artist.Screen key={name} name={name} component={component} />
    ))}
    <Artist.Screen name={ScreenNames.Countries} component={CountriesScreen} />
    <Artist.Screen name={ScreenNames.Market} component={MarketScreen} />
    <Artist.Screen
      name={ScreenNames.MarketCharts}
      component={MarketChartsScreen}
    />
  </Artist.Navigator>
)

const Settings = createStackNavigator()
const SettingsNavigation = () => (
  <Settings.Navigator headerMode="none">
    <Settings.Screen name={ScreenNames.Settings} component={SettingsScreen} />
    <Settings.Screen name={ScreenNames.Developer} component={DeveloperScreen} />
  </Settings.Navigator>
)

const TabNavigator = createBottomTabNavigator()

export const Navigation = () => {
  const user = useContext(UserContext)
  const insets = useSafeAreaInsets()
  const artistId = user.lastUsedArtist?.sonyArtistId

  const artist = artistId
    ? user.artists?.find((a) => a.sonyArtistId === artistId)
    : null ?? user.lastUsedArtist

  if (artist == null) {
    return <ActivityIndicator />
  }

  return (
    <ArtistContext.Provider value={artist}>
      <TabNavigator.Navigator
        initialRouteName={ScreenNames.TracksTab}
        screenOptions={({ route }) => ({
          tabBarIcon: ({ focused, color }) => {
            if (route.name === ScreenNames.TracksTab) {
              return <Library focused={focused} tintColor={color} />
            }

            if (route.name === ScreenNames.Artist) {
              return <Dashboard focused={focused} tintColor={color} />
            }

            if (route.name === ScreenNames.Globe) {
              return <Globe focused={focused} tintColor={color} />
            }

            if (route.name === ScreenNames.SettingsTab) {
              return <SettingsIcon focused={focused} tintColor={color} />
            }

            return <Globe focused={focused} tintColor={color} />
          },
        })}
        tabBarOptions={{
          showLabel: false,
          inactiveTintColor: colors.metals.metal1,
          style: [
            {
              backgroundColor: colors.black,
              borderTopWidth: 0,
              marginTop: 8,
              // Pull buttons closer to the bottom on iPhoneX, etc. phones with rounded bottom corners
              marginBottom: insets.bottom > 0 ? -insets.bottom / 3 : undefined,
            },
          ],
        }}
      >
        <TabNavigator.Screen
          name={ScreenNames.TracksTab}
          component={TracksNavigation}
        />
        <TabNavigator.Screen
          name={ScreenNames.Artist}
          component={ArtistNavigation}
        />
        <TabNavigator.Screen
          name={ScreenNames.CountriesTab}
          component={CountryNavigation}
        />
        <TabNavigator.Screen
          name={ScreenNames.SettingsTab}
          component={SettingsNavigation}
        />
      </TabNavigator.Navigator>
    </ArtistContext.Provider>
  )
}

interface FollowersScreenProps {
  dsp_slug: SocialMedia
  time_interval?: TimeInterval
}

type NavigationParamList = {
  Artist: { artist_id: string }
  ArtistTab: undefined
  ArtistStreamsGraph: {
    market?: string
    dsp: Dsp | 'all'
  }
  Countries: { artist_id?: string; time_interval?: TimeInterval }
  CountriesTab: undefined
  Developer: undefined
  Filter: undefined
  Followers: FollowersScreenProps
  Globe: { artist_id?: string }
  Library: { artist_id: string }
  Login: undefined
  Market: { artist_id?: string; market: string }
  MarketCharts: { market: string; dsp: ChartDsp }
  MarketSelector: {
    previousScreen: keyof NavigationParamList
    topMarketCountryCodes?: string[]
  }
  ProductDetail: { product_id: string; time_interval?: TimeInterval }
  Products: { mode: Mode }
  ProductTracksComparison: { product_id: string }
  Search: undefined
  Settings: undefined
  SettingsTab: undefined
  SocialTab: undefined
  Track: { isrc: string; track?: Track; market?: string }
  TrackCharts: { isrc: string; dsp: ChartDsp; market?: string }
  TrackPlaylist: {
    isrc: string
    playlist_id: string
    market?: string
  }
  TrackPlaylists: { isrc: string; dsp: PlaylistDsp; market?: string }
  Tracks: { mode: Mode }
  TrackList: { mode: TrackListScreenMode }
  TracksTab: undefined
  TracksComparison: { isrcs: string[] }
  TrackStreamsGraph: {
    isrc: string
    dsp: Dsp | 'all'
    market?: string
    time_interval?: TimeInterval
  }
  TrackStreamsSource: { isrc: string; dsp: StreamingDsp | 'all' }
  TrackStreamSources: {
    isrc: string
    dsp: StreamingDsp
    market?: string
  }
  TrackTikTok: { isrc: string; market?: string }
  Video: { video_id: string; market?: string }
  VideoEngagementGraph: { video_id: string; market?: string }
  Videos: { mode: VideosScreenMode }
  VideoViewsGraph: { video_id: string; market?: string }
  VideoViewSources: {
    video_id: string
    market?: string
    dsp: VideoDsp
  }
}

export type ReactNavigationProps<T extends ScreenNames> = {
  route: RouteProp<NavigationParamList, T>
  navigation: NavigationProp<T>
}

export type NavigationProp<T extends ScreenNames> = StackNavigationProp<
  NavigationParamList,
  T
>
