import { FC, ReactElement, useCallback, useEffect, useRef, useState } from "react"
import {
  FlatList,
  Image,
  ImageStyle,
  Platform,
  SectionList,
  TextStyle,
  View,
  ViewStyle,
} from "react-native"
import { Link, RouteProp, useRoute } from "@react-navigation/native"
import { Drawer } from "react-native-drawer-layout"

import { ListItem } from "@/components/ListItem"
import { Screen } from "@/components/Screen"
import { Text } from "@/components/Text"
import { TxKeyPath, isRTL } from "@/i18n"
import { translate } from "@/i18n/translate"
import { MainTabParamList, MainTabScreenProps } from "@/navigators/navigationTypes"
import { useAppTheme } from "@/theme/context"
import { $styles } from "@/theme/styles"
import type { ThemedStyle } from "@/theme/types"
import { s, fs } from "@/utils/responsive"
import { useSafeAreaInsetsStyle } from "@/utils/useSafeAreaInsetsStyle"

import * as Demos from "./demos"
import { DrawerIconButton } from "./DrawerIconButton"
import SectionListWithKeyboardAwareScrollView from "./SectionListWithKeyboardAwareScrollView"

const logo = require("@assets/images/logo.png")

interface DemoListItem {
  item: { name: string; useCases: string[] }
  sectionIndex: number
  handleScroll?: (sectionIndex: number, itemIndex?: number) => void
}

const slugify = (str: string) =>
  str
    .toLowerCase()
    .trim()
    .replace(/[^\w\s-]/g, "")
    .replace(/[\s_-]+/g, "-")
    .replace(/^-+|-+$/g, "")

/**
 * Type-safe utility to check if an unknown object has a valid string property.
 * This is particularly useful in React 19 where props are typed as unknown by default.
 * The function safely narrows down the type by checking both property existence and type.
 * @param props - The unknown props to check.
 * @param propName - The name of the property to check.
 * @returns Whether the property is a valid string.
 */
function hasValidStringProp(props: unknown, propName: string): boolean {
  return (
    props !== null &&
    typeof props === "object" &&
    propName in props &&
    typeof (props as Record<string, unknown>)[propName] === "string"
  )
}

const WebListItem: FC<DemoListItem> = ({ item, sectionIndex }) => {
  const sectionSlug = item.name.toLowerCase()
  const { themed } = useAppTheme()
  return (
    <View>
      <Link screen="Showroom" params={{ queryIndex: sectionSlug }} style={themed($menuContainer)}>
        <Text preset="bold">{item.name}</Text>
      </Link>
      {item.useCases.map((u) => {
        const itemSlug = slugify(u)

        return (
          <Link
            key={`section${sectionIndex}-${u}`}
            screen="Showroom"
            params={{ queryIndex: sectionSlug, itemIndex: itemSlug }}
          >
            <Text>{u}</Text>
          </Link>
        )
      })}
    </View>
  )
}

const NativeListItem: FC<DemoListItem> = ({ item, sectionIndex, handleScroll }) => {
  const { themed } = useAppTheme()
  return (
    <View>
      <Text
        onPress={() => handleScroll?.(sectionIndex)}
        preset="bold"
        style={themed($menuContainer)}
      >
        {item.name}
      </Text>
      {item.useCases.map((u, index) => (
        <ListItem
          key={`section${sectionIndex}-${u}`}
          onPress={() => handleScroll?.(sectionIndex, index)}
          text={u}
          rightIcon={isRTL ? "caretLeft" : "caretRight"}
        />
      ))}
    </View>
  )
}

const ShowroomListItem = Platform.select({ web: WebListItem, default: NativeListItem })
const isAndroid = Platform.OS === "android"

export const ShowroomScreen: FC<MainTabScreenProps<"Showroom">> = function ShowroomScreen(_props) {
  const [open, setOpen] = useState(false)
  const timeout = useRef<ReturnType<typeof setTimeout>>(null)
  const listRef = useRef<SectionList>(null)
  const menuRef = useRef<FlatList<DemoListItem["item"]>>(null)
  const route = useRoute<RouteProp<MainTabParamList, "Showroom">>()
  const params = route.params

  const { themed, theme } = useAppTheme()

  const toggleDrawer = useCallback(() => {
    if (!open) {
      setOpen(true)
    } else {
      setOpen(false)
    }
  }, [open])

  const handleScroll = useCallback((sectionIndex: number, itemIndex = 0) => {
    try {
      listRef.current?.scrollToLocation({
        animated: true,
        itemIndex,
        sectionIndex,
        viewPosition: 0.25,
      })
    } catch (e) {
      console.error(e)
    }
  }, [])

  // handle Web links
  useEffect(() => {
    if (params !== undefined && Object.keys(params).length > 0) {
      const demoValues = Object.values(Demos)
      const findSectionIndex = demoValues.findIndex(
        (x) => x.name.toLowerCase() === params.queryIndex,
      )
      let findItemIndex = 0
      if (params.itemIndex) {
        try {
          findItemIndex = demoValues[findSectionIndex].data({ themed, theme }).findIndex((u) => {
            if (hasValidStringProp(u.props, "name")) {
              return slugify(translate((u.props as { name: TxKeyPath }).name)) === params.itemIndex
            }
            return false
          })
        } catch (err) {
          console.error(err)
        }
      }
      handleScroll(findSectionIndex, findItemIndex)
    }
  }, [handleScroll, params, theme, themed])

  const scrollToIndexFailed = (info: {
    index: number
    highestMeasuredFrameIndex: number
    averageItemLength: number
  }) => {
    listRef.current?.getScrollResponder()?.scrollToEnd()
    timeout.current = setTimeout(
      () =>
        listRef.current?.scrollToLocation({
          animated: true,
          itemIndex: info.index,
          sectionIndex: 0,
        }),
      50,
    )
  }

  useEffect(() => {
    return () => {
      if (timeout.current) {
        clearTimeout(timeout.current)
      }
    }
  }, [])

  const $drawerInsets = useSafeAreaInsetsStyle(["top"])

  return (
    <Drawer
      open={open}
      onOpen={() => setOpen(true)}
      onClose={() => setOpen(false)}
      drawerType="back"
      drawerPosition={isRTL ? "right" : "left"}
      renderDrawerContent={() => (
        <View style={themed([$drawer, $drawerInsets])}>
          <View style={themed($logoContainer)}>
            <Image source={logo} style={$logoImage} />
          </View>
          <FlatList<DemoListItem["item"]>
            ref={menuRef}
            contentContainerStyle={themed($listContentContainer)}
            data={Object.values(Demos).map((d) => ({
              name: d.name,
              useCases: d.data({ theme, themed }).map((u) => {
                if (hasValidStringProp(u.props, "name")) {
                  return translate((u.props as { name: TxKeyPath }).name)
                }
                return ""
              }),
            }))}
            keyExtractor={(item) => item.name}
            renderItem={({ item, index: sectionIndex }) => (
              <ShowroomListItem {...{ item, sectionIndex, handleScroll }} />
            )}
          />
        </View>
      )}
    >
      <Screen
        preset="fixed"
        contentContainerStyle={$styles.flex1}
        {...(isAndroid ? { KeyboardAvoidingViewProps: { behavior: undefined } } : {})}
      >
        <DrawerIconButton onPress={toggleDrawer} />

        <SectionListWithKeyboardAwareScrollView
          ref={listRef}
          contentContainerStyle={themed($sectionListContentContainer)}
          stickySectionHeadersEnabled={false}
          sections={Object.values(Demos).map((d) => ({
            name: d.name,
            description: d.description,
            data: [d.data({ theme, themed })],
          }))}
          renderItem={({ item, index: sectionIndex }) => (
            <View>
              {item.map((demo: ReactElement, demoIndex: number) => (
                <View key={`${sectionIndex}-${demoIndex}`}>{demo}</View>
              ))}
            </View>
          )}
          renderSectionFooter={() => <View style={themed($demoUseCasesSpacer)} />}
          ListHeaderComponent={
            <View style={themed($heading)}>
              <Text preset="heading" tx="showroomScreen:jumpStart" />
            </View>
          }
          onScrollToIndexFailed={scrollToIndexFailed}
          renderSectionHeader={({ section }) => {
            return (
              <View>
                <Text preset="heading" style={themed($demoItemName)}>
                  {section.name}
                </Text>
                <Text style={themed($demoItemDescription)}>{translate(section.description)}</Text>
              </View>
            )
          }}
        />
      </Screen>
    </Drawer>
  )
}

const $drawer: ThemedStyle<ViewStyle> = ({ colors }) => ({
  backgroundColor: colors.background,
  flex: 1,
})

const $listContentContainer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
  paddingHorizontal: spacing.lg,
})

const $sectionListContentContainer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
  paddingHorizontal: spacing.lg,
})

const $heading: ThemedStyle<ViewStyle> = ({ spacing }) => ({
  marginBottom: spacing.xxxl,
})

const $logoImage: ImageStyle = {
  height: s(42),
  width: s(77),
}

const $logoContainer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
  alignSelf: "flex-start",
  justifyContent: "center",
  height: s(56),
  paddingHorizontal: spacing.lg,
})

const $menuContainer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
  paddingBottom: spacing.xs,
  paddingTop: spacing.lg,
})

const $demoItemName: ThemedStyle<TextStyle> = ({ spacing }) => ({
  fontSize: fs(24),
  marginBottom: spacing.md,
})

const $demoItemDescription: ThemedStyle<TextStyle> = ({ spacing }) => ({
  marginBottom: spacing.xxl,
})

const $demoUseCasesSpacer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
  paddingBottom: spacing.xxl,
})
