import { BlurView } from 'expo-blur'
import React, { FC, memo, useState } from 'react'
import { Image, View, useWindowDimensions } from 'react-native'
import {
	runOnJS,
	useAnimatedReaction,
	useDerivedValue,
	useSharedValue,
} from 'react-native-reanimated'
import { LOADER_COLORS } from '../../core/constants'
import { StoryImageProps } from '../../core/dto/componentsDTO'
import Loader from '../Loader'
import ImageStyles from './Image.styles'
import StoryVideo from './video'

import * as Device from 'expo-device'

const StoryImage: FC<StoryImageProps> = ({
	stories,
	activeStory,
	defaultImage,
	isDefaultVideo,
	paused,
	videoProps,
	isActive,
	onImageLayout,
	onLoad,
}) => {
	const { width: WIDTH, height: HEIGHT } = useWindowDimensions()
	const [data, setData] = useState<{
		uri: string | undefined
		isVideo?: boolean
		duration?: number
	}>({ uri: defaultImage, isVideo: isDefaultVideo })

	const loading = useSharedValue(true)
	const color = useSharedValue(LOADER_COLORS)
	const videoDuration = useSharedValue<number | undefined>(undefined)
	const isPaused = useDerivedValue(() => paused.value || !isActive.value)

	const isTablet = Device.deviceType === Device.DeviceType.TABLET

	const onImageChange = async () => {
		if (!activeStory.value) {
			return
		}

		const story = stories.find(item => item.id === activeStory.value)

		if (!story) {
			return
		}

		if (data.uri === story.sourceUrl) {
			if (!loading.value) {
				onLoad(videoDuration.value)
			}
		} else {
			loading.value = true
			setData({
				uri: story.sourceUrl,
				isVideo: story.mediaType === 'video',
				duration: story.duration,
			})
		}

		const nextStory = stories[stories.indexOf(story) + 1]

		if (nextStory && nextStory.mediaType !== 'video') {
			Image.prefetch(nextStory.sourceUrl)
		}
	}

	useAnimatedReaction(
		() => isActive.value,
		(res, prev) => res !== prev && res && runOnJS(onImageChange)(),
		[isActive.value]
	)

	useAnimatedReaction(
		() => activeStory.value,
		(res, prev) => res !== prev && runOnJS(onImageChange)(),
		[activeStory.value]
	)

	const onContentLoad = (duration?: number) => {
		if (data.isVideo) {
			videoDuration.value = duration
		}

		loading.value = false

		if (isActive.value) {
			onLoad(duration)
		}
	}

	return (
		<>
			<View style={ImageStyles.container}>
				<Loader loading={loading} color={color} size={50} />
			</View>
			<View style={ImageStyles.image}>
				{data.uri &&
					(data.isVideo ? (
						<StoryVideo
							onLoad={onContentLoad}
							onLayout={onImageLayout}
							uri={data.uri}
							paused={isPaused}
							isActive={isActive}
							duration={data.duration}
							{...videoProps}
						/>
					) : (
						<View
							style={{
								width: WIDTH,
								height: isTablet ? HEIGHT : undefined,
								position: 'relative',
								// aspectRatio: isTablet ? undefined : 0.5626,
							}}
						>
							<Image
								source={{ uri: data.uri }}
								style={{
									width: WIDTH,
									aspectRatio: isTablet ? undefined : 0.5626,
									height: isTablet ? HEIGHT : undefined,
								}}
								resizeMode={isTablet ? 'contain' : 'cover'}
								testID='storyImageComponent'
								onLayout={e =>
									onImageLayout(Math.min(HEIGHT, e.nativeEvent.layout.height))
								}
								onLoad={() => onContentLoad()}
							/>
							{isTablet && (
								<>
									<Image
										source={{ uri: data.uri }}
										style={{
											width: WIDTH,
											height: HEIGHT,
											position: 'absolute',
											left: 0,
											right: 0,
											bottom: 0,
											zIndex: 1,
										}}
										resizeMode={'cover'}
										testID='storyImageComponent'
										onLayout={e =>
											onImageLayout(
												Math.min(HEIGHT, e.nativeEvent.layout.height)
											)
										}
										onLoad={() => onContentLoad()}
									/>
									<BlurView
										intensity={100}
										style={{
											position: 'absolute',
											left: 0,
											right: 0,
											bottom: 0,
											zIndex: 1,
											width: WIDTH,
											height: HEIGHT,
										}}
									></BlurView>
								</>
							)}
						</View>
					))}
			</View>
		</>
	)
}

export default memo(StoryImage)
