import type { BottomTabNavigationOptions } from '@react-navigation/bottom-tabs'
import type {
  DefaultNavigatorOptions,
  NavigationAction,
  NavigationProp,
  ParamListBase,
  TabActionHelpers,
  TabNavigationState,
  TabRouterOptions,
  useNavigationBuilder,
} from '@react-navigation/native'
import { createContext, type ComponentType, type PropsWithChildren } from 'react'

import type { TriggerMap } from './common'

export type ExpoTabsProps = ExpoTabsNavigatorOptions

export type ExpoTabsNavigatorScreenOptions = {
  detachInactiveScreens?: boolean
  unmountOnBlur?: boolean
  freezeOnBlur?: boolean
  lazy?: boolean
}

export type ExpoTabsNavigatorOptions = DefaultNavigatorOptions<
  ParamListBase,
  TabNavigationState<ParamListBase>,
  ExpoTabsScreenOptions,
  TabNavigationEventMap,
  ExpoTabsNavigationProp<ParamListBase>
> &
  // Should be set through `unstable_settings`
  Omit<TabRouterOptions, 'initialRouteName'> &
  ExpoTabsNavigatorScreenOptions

export type ExpoTabsNavigationProp<
  ParamList extends ParamListBase,
  RouteName extends keyof ParamList = keyof ParamList,
> = NavigationProp<
  ParamList,
  RouteName,
  TabNavigationState<ParamListBase>,
  ExpoTabsScreenOptions,
  TabNavigationEventMap
>

export type ExpoTabsScreenOptions = Pick<BottomTabNavigationOptions, 'title' | 'lazy'> & {
  freezeOnBlur?: boolean
  params?: object
  title: string
  action: NavigationAction
}

export type TabNavigationEventMap = {
  /**
   * Event which fires on tapping on the tab in the tab bar.
   */
  tabPress: { data: undefined; canPreventDefault: true }
  /**
   * Event which fires on long press on the tab in the tab bar.
   */
  tabLongPress: { data: undefined }
}

/**
 * The React Navigation custom navigator.
 *
 * @see [`useNavigationBuilder`](https://reactnavigation.org/docs/custom-navigators/#usenavigationbuilder) hook from React Navigation for more information.
 */
export type TabsContextValue = Omit<
  ReturnType<
    typeof useNavigationBuilder<
      TabNavigationState<any>,
      TabRouterOptions,
      TabActionHelpers<ParamListBase>,
      ExpoTabsNavigatorScreenOptions,
      TabNavigationEventMap
    >
  >,
  'render'
> & { NavigationContent: ComponentType<PropsWithChildren> }

export type TabContextValue = TabsDescriptor['options']

export const TabContext = createContext<TabContextValue>({})
/**
 * @hidden
 */
export const TabTriggerMapContext = createContext<TriggerMap>({})
/**
 * @hidden
 */
export const TabsDescriptorsContext = createContext<TabsContextValue['descriptors']>({})
/**
 * @hidden
 */
export const TabsNavigatorContext = createContext<TabsContextValue['navigation'] | null>(
  null
)
/**
 * @hidden
 */
export const TabsStateContext = createContext<TabsContextValue['state']>({
  type: 'tab',
  preloadedRouteKeys: [],
  history: [],
  index: -1,
  key: '',
  stale: false,
  routeNames: [],
  routes: [],
})

export type Route = TabNavigationState<ParamListBase>['routes'][number]
export type TabsDescriptor = TabsContextValue['descriptors'][number]
