import { useNavigation } from "@react-navigation/native";
import type { ListRenderItem } from "@shopify/flash-list";
import { MAX_PHOTOS_ALLOWED } from "components/Camera/StandardCamera/StandardCamera";
import {
  Body2,
  Button,
  ButtonBar,
  CustomFlashList,
  FloatingActionBar,
  INatIcon,
  INatIconButton,
} from "components/SharedComponents";
import ViewWrapper from "components/SharedComponents/ViewWrapper";
import { Pressable, View } from "components/styledComponents";
import React, { useCallback, useMemo, useState } from "react";
import type { LayoutChangeEvent } from "react-native";
import { useGridLayout, useTranslation } from "sharedHooks";
import colors from "styles/tailwindColors";

import GroupPhotoImage from "./GroupPhotoImage";

const emptyItemStyle = {
  borderWidth: 4,
  borderStyle: "dashed",
  borderColor: colors.mediumGray,
} as const;

interface Item {
  photos: {
    image: {
      uri: string;
    };
  }[];
}

type GroupPhotosListItem = Item | { empty: true };

function isEmptyGridItem( item: GroupPhotosListItem ): item is { empty: true } {
  return "empty" in item && item.empty === true;
}

interface Props {
  combinePhotos: ( ) => void;
  groupedPhotos: Item[];
  isCreatingObservations?: boolean;
  navBasedOnUserSettings: ( ) => void;
  removePhotos: ( ) => void;
  selectedObservations: Item[];
  selectObservationPhotos: ( isSelected: boolean, item: Item ) => void;
  separatePhotos: ( ) => void;
  totalPhotos: number;
}

const GroupPhotos = ( {
  combinePhotos,
  groupedPhotos,
  isCreatingObservations,
  navBasedOnUserSettings,
  removePhotos,
  selectedObservations,
  selectObservationPhotos,
  separatePhotos,
  totalPhotos,
}: Props ) => {
  const { t } = useTranslation( );
  const navigation = useNavigation( );
  const {
    flashListStyle,
    gridItemStyle,
    numColumns,
  } = useGridLayout( );
  const [buttonBarHeight, setButtonBarHeight] = useState<number | null>( null );
  const extractKey = ( item: GroupPhotosListItem, index: number ) => (
    isEmptyGridItem( item )
      ? "empty"
      : `${item.photos[0].image.uri}${index}`
  );

  const noObsSelected = selectedObservations.length === 0;
  const oneObsSelected = selectedObservations.length === 1;
  const obsWithMultiplePhotosSelected
    = selectedObservations?.[0]?.photos?.length > 1;

  const renderImage = useCallback( ( item: Item ) => (
    <GroupPhotoImage
      item={item}
      selectedObservations={selectedObservations}
      selectObservationPhotos={selectObservationPhotos}
      style={gridItemStyle}
    />
  ), [gridItemStyle, selectedObservations, selectObservationPhotos] );

  const addPhotos = useCallback( () => {
    navigation.navigate( "NoBottomTabStackNavigator", {
      screen: "PhotoLibrary",
      params: { fromGroupPhotos: true },
    } );
  }, [navigation] );

  const renderItem: ListRenderItem<GroupPhotosListItem> = useCallback( ( { item } ) => {
    if ( isEmptyGridItem( item ) ) {
      return (
        <Pressable
          accessibilityRole="button"
          onPress={addPhotos}
          className="rounded-[15px] justify-center items-center"
          // Sorry, couldn't get this to work with tailwind
          style={[gridItemStyle, emptyItemStyle]}
        >
          <INatIcon name="plus" size={50} color={colors.mediumGray} />
        </Pressable>
      );
    }
    return renderImage( item );
  }, [gridItemStyle, renderImage, addPhotos] );

  const headerComponent = useMemo( ( ) => (
    <View className="m-5">
      <Body2>{t( "Group-photos-onboarding" )}</Body2>
    </View>
  ), [t] );

  const onLayout = ( event: LayoutChangeEvent ) => {
    const {
      height,
    } = event.nativeEvent.layout;
    setButtonBarHeight( height );
  };

  const data = useMemo( (): GroupPhotosListItem[] => {
    const newData: GroupPhotosListItem[] = [...groupedPhotos];
    if ( totalPhotos < MAX_PHOTOS_ALLOWED ) {
      newData.push( { empty: true } );
    }
    return newData;
  }, [groupedPhotos, totalPhotos] );

  const extraData = {
    selectedObservations,
  };

  return (
    <ViewWrapper useTopInset={false}>
      <CustomFlashList
        ListHeaderComponent={headerComponent}
        contentContainerStyle={flashListStyle}
        data={data}
        extraData={extraData}
        key={numColumns}
        keyExtractor={extractKey}
        numColumns={numColumns}
        renderItem={renderItem}
        testID="GroupPhotos.list"
      />
      <FloatingActionBar
        show={selectedObservations.length > 0 && typeof buttonBarHeight === "number"}
        position="bottomStart"
        containerClass="ml-[15px] rounded-md"
        footerHeight={buttonBarHeight ?? 0}
      >
        <View className="rounded-md overflow-hidden flex-row">
          <INatIconButton
            icon="combine"
            mode="contained"
            size={20}
            color={colors.white}
            backgroundColor={colors.darkGray}
            className="m-4"
            accessibilityLabel={t( "Combine-Photos" )}
            disabled={noObsSelected || oneObsSelected}
            onPress={combinePhotos}
          />
          <INatIconButton
            icon="separate"
            mode="contained"
            size={20}
            color={colors.white}
            backgroundColor={colors.darkGray}
            className="m-4"
            accessibilityLabel={t( "Separate-Photos" )}
            disabled={!obsWithMultiplePhotosSelected}
            onPress={separatePhotos}
          />
          <INatIconButton
            icon="trash-outline"
            mode="contained"
            size={20}
            color={colors.white}
            backgroundColor={colors.warningRed}
            className="m-4"
            accessibilityLabel={t( "Remove-Photos" )}
            disabled={noObsSelected}
            onPress={removePhotos}
          />
        </View>
      </FloatingActionBar>
      <ButtonBar
        sticky
        containerClass="items-center z-50 bg-white"
        onLayout={onLayout}
      >
        <Button
          className="max-w-[500px] w-full"
          level="focus"
          text={t( "IMPORT-X-OBSERVATIONS", { count: groupedPhotos.length } )}
          onPress={navBasedOnUserSettings}
          testID="GroupPhotos.next"
          loading={isCreatingObservations}
        />
      </ButtonBar>
    </ViewWrapper>
  );
};

export default GroupPhotos;
