import BottomSheet, {
  BottomSheetBackdrop,
  BottomSheetBackdropProps,
  BottomSheetFlashList,
} from "@gorhom/bottom-sheet";
import React, {
  forwardRef,
  memo,
  useCallback,
  useImperativeHandle,
  useMemo,
  useRef,
  useState,
} from "react";
import { Pressable, Text, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import Ionicon from "@expo/vector-icons/Ionicons";
import { IoniconsType } from "../../lib/types";
import { ListRenderItemInfo } from "@shopify/flash-list";
import { Input } from "./Input";
import { useDebounce } from "../../hooks/useDebounce";
import { StatusBar } from "expo-status-bar";

export interface CustomBottomSheetHandle {
  showSheet: () => void;
  hideSheet: () => void;
  isVisible: () => boolean;
}

export type CustomBottomSheetProps = {
  defaultOpen?: boolean;
  children: React.ReactNode;
  snapPoints?: (number | string)[];
  handleSheetClose?: (index: number) => void;
  topInset?: number;
  bottomInset?: number;
};

export const CustomBottomSheet = forwardRef<
  CustomBottomSheetHandle,
  CustomBottomSheetProps
>(
  (
    {
      children,
      snapPoints = ["50%"],
      handleSheetClose,
      defaultOpen = false,
      topInset,
      bottomInset,
    },
    ref
  ) => {
    const sheetRef = useRef<BottomSheet>(null);
    const [isVisible, setIsVisible] = useState(defaultOpen);

    useImperativeHandle(
      ref,
      () => ({
        showSheet() {
          setIsVisible(true);
          sheetRef.current?.snapToIndex(0);
        },

        hideSheet() {
          setIsVisible(false);
          sheetRef.current?.close();
        },
        isVisible() {
          return isVisible;
        },
      }),
      [setIsVisible]
    );

    const renderBackdrop = useCallback(
      (props: BottomSheetBackdropProps) => (
        <BottomSheetBackdrop
          {...props}
          disappearsOnIndex={-1}
          appearsOnIndex={0}
          onPress={() => sheetRef.current?.close()}
        />
      ),
      []
    );

    const handleSheetChange = useCallback(
      (index: number) => {
        if ((index !== -1) !== isVisible) {
          setIsVisible(index !== -1);
        }
        if (index === -1 && handleSheetClose) {
          handleSheetClose(index);
        }
      },
      [handleSheetClose]
    );

    const insets = useSafeAreaInsets();

    if (!isVisible) return null;

    return (
      <BottomSheet
        ref={sheetRef}
        enablePanDownToClose={true}
        enableDynamicSizing={false}
        backdropComponent={renderBackdrop}
        onChange={handleSheetChange}
        snapPoints={snapPoints}
        index={isVisible ? 0 : -1}
        topInset={topInset !== undefined ? topInset : insets.top}
        bottomInset={
          bottomInset !== undefined ? bottomInset : insets.bottom
        }
      >
        <StatusBar translucent={true} />

        {children}
      </BottomSheet>
    );
  }
);

export function CustomBottomSheetTitle({
  title,
  subTitle,
}: {
  title: string;
  subTitle: string;
}) {
  return (
    <>
      <Text className="text-center text-xl font-semibold text-black">
        {title}
      </Text>
      <Text className="border-b border-gray-100 pb-4 text-center text-sm text-gray-500">
        {subTitle}
      </Text>
    </>
  );
}

export type CustomBottomSheetSelectItemType = {
  icon?: IoniconsType;
  iconContent?: React.ReactNode;
  name: string;
  descriptionContent?: React.ReactNode;
  description?: string;
  id: string;
};
export const CustomBottomSheetSelectItem = memo(
  ({
    isActive,
    item,
    handleOnPress,
  }: {
    isActive: boolean;
    item: CustomBottomSheetSelectItemType;
    handleOnPress: (id: string) => void;
  }) => {
    return (
      <Pressable
        onPress={() => handleOnPress(item.id)}
        className="h-16 flex-row items-center"
      >
        {item.iconContent ||
          (item.icon && (
            <View className="mr-3 h-12 w-12 items-center justify-center rounded-full bg-gray-50">
              <Ionicon name={item.icon} size={24} color="#4b5563" />
            </View>
          ))}
        <View className="flex-1">
          <Text className="text-sm font-medium text-gray-900">
            {item.name}
          </Text>
          {item.descriptionContent ||
            (item.description && (
              <Text className="text-xs text-gray-500">
                {item.description}
              </Text>
            ))}
        </View>
        {isActive && (
          <Ionicon name="checkmark-circle" size={24} color="#ef4444" />
        )}
      </Pressable>
    );
  }
);
export function CustomBottomSheetSelect({
  activeItem,
  items,
  handleOnPress,
  searchable,
}: {
  activeItem?: string;
  items: CustomBottomSheetSelectItemType[];
  handleOnPress: (id: string) => void;
  searchable?: boolean;
}) {
  const [searchInput, setSearchInput] = useState<string>("");
  const searchInputDelay = useDebounce(searchInput, 500);
  const filteredItems = useMemo(
    () => items.filter((i) => i.name.includes(searchInput)),
    [searchInputDelay]
  );
  const keyExtractor = useCallback((item: { id: string }) => item.id, []);
  const renderItem = useCallback(
    ({ item }: ListRenderItemInfo<CustomBottomSheetSelectItemType>) => (
      <CustomBottomSheetSelectItem
        item={item}
        isActive={activeItem === item.id}
        handleOnPress={handleOnPress}
      />
    ),
    [activeItem, handleOnPress]
  );
  return (
    <>
      {searchable && (
        <View className="px-4">
          <Input
            className="border-t-2"
            placeholder="Search"
            icon="search"
            autoFocus={true}
            focusable
            onChangeText={setSearchInput}
          />
        </View>
      )}
      <BottomSheetFlashList
        className="mx-4"
        nestedScrollEnabled={true}
        data={filteredItems}
        keyExtractor={keyExtractor}
        renderItem={renderItem}
        estimatedItemSize={64}
      />
    </>
  );
}
