import { useEffect, useRef, useState, useCallback } from 'react';
import { Dimensions, FlatList, Image, Modal, StyleSheet, TouchableOpacity, View } from 'react-native';
import { ImageObject, GalleryProps, RenderImageProps } from './types';
import ImagePreview from './image-preview';
import SwipeContainer from './swipe-container';
import { DEFAULT_THUMB_COLOR, DEFAULT_THUMB_SIZE } from './constants';

const { height: deviceHeight, width: deviceWidth } = Dimensions.get('window');

const ImageGallery: React.FC<GalleryProps> = ({
	close,
	hideThumbs = false,
	images = [],
	initialIndex = 0,
	isOpen,
	renderCustomImage,
	renderCustomThumb,
	renderFooterComponent,
	renderHeaderComponent,
	resizeMode = 'contain',
	thumbColor = DEFAULT_THUMB_COLOR,
	thumbResizeMode = 'cover',
	thumbSize = DEFAULT_THUMB_SIZE,
	disableSwipe = false
}) => {
	const [activeIndex, setActiveIndex] = useState(initialIndex);
	const [isDragging, setIsDragging] = useState(false);
	const topRef = useRef<FlatList<ImageObject | any>>(null);
	const bottomRef = useRef<FlatList<ImageObject>>(null);

	const keyExtractor = useCallback((item: ImageObject, index: number) => item.id?.toString() ?? index.toString(), []);

	const scrollToIndex = useCallback(
		(index: number) => {
			if (!isOpen || index < 0 || index >= images.length) return;

			setActiveIndex(index);

			const scrollOptions = {
				animated: true,
				index,
				viewPosition: 0.5
			};

			try {
				if (topRef.current) {
					topRef.current.scrollToIndex(scrollOptions);
				}

				if (bottomRef.current && !hideThumbs) {
					bottomRef.current.scrollToIndex(scrollOptions);
				}
			} catch (error) {
				console.warn('Error scrolling to index:', error);
			}
		},
		[hideThumbs, isOpen, images.length]
	);

	const renderItem = useCallback(
		({ item, index }: RenderImageProps) => (
			<ImagePreview
				index={index}
				isSelected={activeIndex === index}
				item={item}
				resizeMode={resizeMode}
				renderCustomImage={renderCustomImage}
			/>
		),
		[activeIndex, resizeMode, renderCustomImage]
	);

	const renderThumb = useCallback(
		({ item, index }: RenderImageProps) => (
			<TouchableOpacity onPress={() => scrollToIndex(index)} activeOpacity={0.8}>
				{renderCustomThumb ? (
					renderCustomThumb(item, index, activeIndex === index)
				) : (
					<Image
						resizeMode={thumbResizeMode}
						style={[
							styles.thumb,
							{ width: thumbSize, height: thumbSize },
							activeIndex === index && { ...styles.activeThumb, borderColor: thumbColor }
						]}
						source={{ uri: item.thumbUrl || item.url }}
					/>
				)}
			</TouchableOpacity>
		),
		[activeIndex, thumbColor, thumbSize, thumbResizeMode, renderCustomThumb, scrollToIndex]
	);

	const onMomentumEnd = useCallback(
		(e: { nativeEvent: { contentOffset: { x: number } } }) => {
			const { x } = e.nativeEvent.contentOffset;
			scrollToIndex(Math.round(x / deviceWidth));
		},
		[deviceWidth, scrollToIndex]
	);

	useEffect(() => {
		// Only set the initial index when opening the gallery
		if (isOpen && initialIndex >= 0 && initialIndex < images.length) {
			setActiveIndex(initialIndex);
		} else if (!isOpen) {
			// Reset the active index when closing, but don't scroll
			setActiveIndex(0);
		}
	}, [isOpen, initialIndex, images.length]);

	const getItemLayout = useCallback(
		(_: any, index: number) => ({
			length: deviceWidth,
			offset: deviceWidth * index,
			index
		}),
		[deviceWidth]
	);

	const getThumbLayout = useCallback(
		<T extends unknown>(_: ArrayLike<T> | null | undefined, index: number) => ({
			length: thumbSize,
			offset: thumbSize * index,
			index
		}),
		[thumbSize]
	);

	return (
		<Modal animationType={isOpen ? 'slide' : 'fade'} visible={isOpen}>
			<View style={styles.container}>
				{images.length > 0 && (
					<>
						<SwipeContainer disableSwipe={disableSwipe} setIsDragging={setIsDragging} close={close}>
							<FlatList
								initialScrollIndex={initialIndex < images.length ? initialIndex : 0}
								getItemLayout={getItemLayout}
								data={images}
								horizontal
								keyExtractor={keyExtractor}
								onMomentumScrollEnd={onMomentumEnd}
								pagingEnabled
								ref={topRef}
								renderItem={renderItem}
								scrollEnabled={!isDragging}
								showsHorizontalScrollIndicator={false}
								windowSize={3}
								maxToRenderPerBatch={3}
								removeClippedSubviews={true}
								initialNumToRender={1}
							/>
						</SwipeContainer>

						{!hideThumbs && (
							<FlatList
								initialScrollIndex={initialIndex < images.length ? initialIndex : 0}
								getItemLayout={getThumbLayout}
								contentContainerStyle={styles.thumbnailListContainer}
								data={images}
								horizontal
								keyExtractor={keyExtractor}
								pagingEnabled
								ref={bottomRef}
								renderItem={renderThumb}
								showsHorizontalScrollIndicator={false}
								style={[styles.bottomFlatlist, { bottom: thumbSize }]}
								windowSize={3}
								maxToRenderPerBatch={3}
								removeClippedSubviews={true}
								initialNumToRender={1}
							/>
						)}
					</>
				)}

				{renderHeaderComponent && images.length > 0 && (
					<View style={styles.header}>{renderHeaderComponent(images[activeIndex], activeIndex)}</View>
				)}

				{renderFooterComponent && images.length > 0 && (
					<View style={styles.footer}>{renderFooterComponent(images[activeIndex], activeIndex)}</View>
				)}
			</View>
		</Modal>
	);
};

const styles = StyleSheet.create({
	container: {
		alignItems: 'center',
		backgroundColor: 'black',
		flex: 1,
		height: deviceHeight,
		justifyContent: 'center',
		width: deviceWidth
	},
	header: {
		position: 'absolute',
		top: 0,
		width: '100%'
	},
	footer: {
		bottom: 0,
		position: 'absolute',
		width: '100%'
	},
	activeThumb: {
		borderWidth: 3
	},
	thumb: {
		borderRadius: 12,
		marginRight: 10
	},
	thumbnailListContainer: {
		paddingHorizontal: 10
	},
	bottomFlatlist: {
		position: 'absolute'
	}
});

export default ImageGallery;
