import { Image } from 'expo-image';
import { useVideoPlayer, VideoView } from 'expo-video';
import { memo, useCallback, useEffect, useMemo, useState } from 'react';
import { StyleSheet, View } from 'react-native';
import type { VideoPlayerProps } from './types';
import { useSharedVisibility } from './useSharedVisibility';
import { getVideoThumbnail, getVideoUrl } from '@/lib/utils/media';

const videoViewStyle = {
  width: '100%',
  height: '100%',
  position: 'absolute' as const,
  top: 0,
  left: 0,
  right: 0,
  bottom: 0
};

const originalImageStyle = {
  width: 64,
  height: 64,
  position: 'absolute' as const,
  bottom: 8,
  left: 8,
  borderRadius: 12,
  borderWidth: 1,
  borderColor: "#ffffff",
  zIndex: 99
};

const imageStyle = {
  width: '100%',
  borderWidth: 0
};

function VideoPlayerComponent({
  source,
  originalImage,
  style,
  dwellTime = 500,
  threshold = 0.1
}: VideoPlayerProps) {
  const [imageAspectRatio, setImageAspectRatio] = useState(1);
  const { ref: viewRef, isVisible, shouldPlay } = useSharedVisibility(threshold, dwellTime);

  const url = useMemo(() => {
    return source?.uri
  }, [source])

  const isVideo = useMemo(() => {
    return /\.(mp4|webm|ogg|mov|avi)$/i.test(url || ``)
  }, [url])

  const thumbnailUrl = useMemo(() => {
    if (!isVideo) return url;
    return getVideoThumbnail(url!, { time: '0s', width: 600, height: 600, fit: 'cover' });
  }, [url, isVideo]);

  const player = useVideoPlayer(
    isVideo ? { ...source, uri: getVideoUrl(source.uri!) } : null,
    (p) => {
      p.loop = true;
      p.muted = true;
    }
  )

  useEffect(() => {
    if (!isVideo || !player) return;

    try {
      shouldPlay ? player.play() : player.pause();
    } catch { }
  }, [shouldPlay, player, isVideo]);

  const handleImageLoad = useCallback((e: any) => {
    const { width, height } = e.source;
    if (width && height) {
      setImageAspectRatio(width / height);
    }
  }, []);

  const element = useMemo(() => {
    if (!isVisible) return null;
    if (isVideo && player) {
      return <>
        <VideoView
          player={player}
          contentFit="cover"
          nativeControls={false}
          style={videoViewStyle}
        />
        {originalImage && <Image source={{ uri: originalImage }} style={originalImageStyle} />}
      </>
    }
    else {
      return <Image
        source={{ uri: thumbnailUrl }}
        contentFit="cover"
        onLoad={handleImageLoad}
        style={[imageStyle, { aspectRatio: imageAspectRatio }]}
      />
    }
  }, [isVideo, isVisible, imageAspectRatio, player, thumbnailUrl, originalImage, handleImageLoad])

  return (
    <View ref={viewRef as any} style={[styles.container, style]}>
      {element}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    width: '100%',
    height: '100%',
    overflow: 'hidden'
  }
});

export default memo(VideoPlayerComponent);
