import { useIsFocused } from "@react-navigation/native";
import { useAudioPlayer } from "expo-audio";
import { BlurView } from "expo-blur";
import { VideoView, useVideoPlayer } from "expo-video";
import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import { Image, Platform, Pressable, Text, View } from "react-native";
import Carousel from "react-native-reanimated-carousel";
import { responsiveHeight } from "react-native-responsive-dimensions";
import { icons, img } from "../assets";
import { openComments } from "../components/bottomsheets/CommentsBottomSheet";
import KaraokeLyrics from "../components/KaraokeLyrics";
import {
  arrayRemove,
  arrayUnion,
  projectsRef,
  usersRef,
} from "../config/firebase";
import useDataFromRef from "../hooks/useDataFromRef";
import { Routes } from "../navigation";
import { navigate } from "../navigation/NavigationService";
import { useUser } from "../providers/UserDataProvider";
import { Palette } from "../styles";
import { FONT_FAMILY } from "../styles/Fonts";
import { size } from "../styles/Style";

const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
  const { currentUID, followUser, unfollowUser } = useUser() || {};
  const videoUrl = item?.playbackUrl || null;
  const audioSource = useMemo(() => {
    const fromSong = item?.songUrl ? { uri: item.songUrl } : null;
    return fromSong;
  }, [item]);

  const hasExternalAudio = !!audioSource;

  const initialLikedBy = Array.isArray(item?.likedBy) ? item.likedBy : [];
  const [isLiked, setIsLiked] = useState(
    currentUID ? initialLikedBy.includes(currentUID) : false
  );
  const [likesCount, setLikesCount] = useState(initialLikedBy.length);

  const [owner, setOwner] = useState(
    item?.userId && userCache?.current?.get(item.userId)
      ? userCache.current.get(item.userId)
      : null
  );
  useEffect(() => {
    let cancelled = false;
    const run = async () => {
      try {
        const uid = item?.userId;
        if (!uid || !userCache) return;
        const cached = userCache.current.get(uid);
        if (cached) {
          if (!cancelled) setOwner(cached);
          return;
        }
        const user = await getUserByUid?.(uid);
        if (!cancelled && user) {
          userCache.current.set(uid, user);
          setOwner(user);
        }
      } catch (e) {}
    };
    run();
    return () => {
      cancelled = true;
    };
  }, [item?.userId, userCache, getUserByUid]);

  // Live sync owner from Firestore to reflect follow changes elsewhere
  useEffect(() => {
    const uid = item?.userId;
    if (!uid) return;
    const unsub = usersRef.doc(uid).onSnapshot(
      (doc) => {
        if (doc?.exists) {
          const data = { id: doc.id, ...doc.data() };
          setOwner(data);
          try {
            userCache?.current?.set(uid, data);
          } catch (e) {}
        }
      },
      () => {}
    );
    return () => unsub?.();
  }, [item?.userId, userCache]);

  // Follow state derived from owner.followedBy
  const [isFollowing, setIsFollowing] = useState(false);
  useEffect(() => {
    const list = Array.isArray(owner?.followedBy) ? owner.followedBy : [];
    setIsFollowing(currentUID ? list.includes(currentUID) : false);
  }, [owner?.followedBy, currentUID]);

  useEffect(() => {
    const lb = Array.isArray(item?.likedBy) ? item.likedBy : [];
    setLikesCount(lb.length);
    setIsLiked(currentUID ? lb.includes(currentUID) : false);
  }, [item?.likedBy, currentUID]);
  console.log("has external audio : ", hasExternalAudio);

  const audioPlayer = useAudioPlayer(audioSource || undefined);
  const videoPlayer = useVideoPlayer(videoUrl || null, (p) => {
    p.loop = false;
    p.muted = true;
    p.timeUpdateEventInterval = 0.2;
  });

  useEffect(() => {
    const toggle = async () => {
      try {
        if (isActive) {
          try {
            if (audioPlayer && hasExternalAudio) await audioPlayer.seekTo?.(0);
          } catch (e) {}
          try {
            if (videoPlayer) videoPlayer.currentTime = 0;
          } catch (e) {}

          // Lancer quasi simultanément (éviter await pour limiter le décalage)
          try {
            if (videoPlayer) videoPlayer.play();
          } catch (e) {}
          try {
            if (audioPlayer && hasExternalAudio) audioPlayer.play?.();
          } catch (e) {}
        } else {
          if (audioPlayer?.playing) await audioPlayer.pause?.();
          if (videoPlayer?.playing) videoPlayer.pause();
        }
      } catch (e) {}
    };
    toggle();
  }, [isActive, audioPlayer, videoPlayer, hasExternalAudio]);

  // Micro-correction initiale uniquement pour absorber un léger décalage réseau
  useEffect(() => {
    if (!isActive || !hasExternalAudio) return;
    const t = setTimeout(() => {
      try {
        const a = audioPlayer?.currentTime || 0;
        const v = videoPlayer?.currentTime || 0;
        if (Math.abs(a - v) > 0.2 && videoPlayer) {
          videoPlayer.currentTime = Math.max(0, a);
        }
      } catch (e) {}
    }, 300);
    return () => clearTimeout(t);
  }, [isActive, hasExternalAudio, audioPlayer, videoPlayer]);

  useEffect(() => {
    return () => {
      try {
        if (audioPlayer?.playing) audioPlayer.pause?.();
        if (videoPlayer?.playing) videoPlayer.pause();
      } catch (e) {}
    };
  }, [audioPlayer, videoPlayer]);

  // Build alignedWords from item musicTimestamps
  const alignedWords = useMemo(() => {
    const idx = Number(item?.songIndex) || 0;
    const ts = item?.musicTimestamps?.[idx];

    const arr = Array.isArray(ts?.alignedWords) ? ts.alignedWords : [];
    return arr.map((w) => ({
      word: String(w?.word ?? ""),
      startS: Number(w?.startS ?? 0),
      endS: Number(w?.endS ?? 0),
    }));
  }, [item?.musicTimestamps, item?.songIndex]);

  // Track current time for lyrics sync
  const [currentTimeS, setCurrentTimeS] = useState(0);
  useEffect(() => {
    if (!isActive) return;
    const id = setInterval(() => {
      try {
        const t = hasExternalAudio
          ? Number(audioPlayer?.currentTime || 0)
          : Number(videoPlayer?.currentTime || 0);
        setCurrentTimeS(t);
      } catch (e) {}
    }, 250);
    return () => clearInterval(id);
  }, [isActive, hasExternalAudio, audioPlayer, videoPlayer]);

  return (
    <View
      style={{
        height: responsiveHeight(100),
        position: "relative",
        backgroundColor: "black",
      }}
    >
      {!!videoUrl ? (
        <VideoView
          player={videoPlayer}
          nativeControls={false}
          contentFit="cover"
          style={{ width: "100%", height: "100%" }}
        />
      ) : (
        <Image
          source={img.placeholder3}
          style={{ width: "100%", height: "100%" }}
        />
      )}

      {/* Right side actions */}
      <View
        style={{
          position: "absolute",
          width: "100%",
          bottom: 130,
          gap: 18,
        }}
      >
        <View
          style={{
            alignSelf: "flex-end",
            alignItems: "center",
            gap: 20,
            paddingHorizontal: 13,
          }}
        >
          <View style={{ gap: 6, alignItems: "center" }}>
            <Pressable
              onPress={() => {
                navigate(Routes.SingerProfile, { userId: item?.userId });
              }}
            >
              {owner?.profilePictureURL ? (
                <Image
                  source={{ uri: owner.profilePictureURL }}
                  style={{
                    ...size({ size: 45 }),
                    borderRadius: 100,
                  }}
                />
              ) : (
                <Image
                  source={img.profile}
                  style={{
                    ...size({ size: 45 }),
                    borderRadius: 100,
                  }}
                />
              )}
            </Pressable>
            {owner?.id && currentUID && owner.id !== currentUID && (
              <Pressable
                onPress={async () => {
                  try {
                    const next = !isFollowing;
                    setIsFollowing(next);
                    // Optimistic update of local owner.followedBy
                    setOwner((prev) => {
                      const fb = Array.isArray(prev?.followedBy)
                        ? prev.followedBy
                        : [];
                      const newFb = next
                        ? Array.from(new Set([...fb, currentUID]))
                        : fb.filter((x) => x !== currentUID);
                      return prev ? { ...prev, followedBy: newFb } : prev;
                    });
                    if (next) await followUser?.(owner.id);
                    else await unfollowUser?.(owner.id);
                  } catch (e) {
                    // rollback on failure
                    setIsFollowing((v) => !v);
                  }
                }}
              >
                <BlurView
                  tint="dark"
                  intensity={20}
                  style={{
                    paddingVertical: 6,
                    paddingHorizontal: 12,
                    borderRadius: 12,
                    borderWidth: 1,
                    borderColor: Palette.white,
                    overflow: "hidden",
                    backgroundColor: isFollowing ? "#FFFFFF1A" : undefined,
                  }}
                  experimentalBlurMethod={
                    Platform.OS !== "ios" ? "dimezisBlurView" : "none"
                  }
                >
                  <Text
                    style={{
                      fontSize: 13,
                      color: Palette.white,
                      fontFamily: FONT_FAMILY.InterMedium,
                    }}
                  >
                    {isFollowing ? "Ne plus suivre" : "Suivre"}
                  </Text>
                </BlurView>
              </Pressable>
            )}
          </View>
          <Pressable
            onPress={async () => {
              try {
                if (!currentUID || !item?.id) return;
                const nextLiked = !isLiked;
                setIsLiked(nextLiked);
                setLikesCount((c) => Math.max(0, c + (nextLiked ? 1 : -1)));

                const ref = projectsRef.doc(item.id);
                await ref.set(
                  {
                    likedBy: nextLiked
                      ? arrayUnion(currentUID)
                      : arrayRemove(currentUID),
                    // Optionally: updatedAt could be set if needed
                  },
                  { merge: true }
                );
              } catch (e) {
                // rollback on failure
                setIsLiked((v) => !v);
                setLikesCount((c) => (isLiked ? c + 1 : Math.max(0, c - 1)));
              }
            }}
            style={{ alignItems: "center" }}
          >
            <Image
              source={isLiked ? icons.heart : icons.heartOutline}
              style={size({ size: 26 })}
              resizeMode="contain"
            />
            {!!likesCount && (
              <Text
                style={{
                  color: Palette.white,
                  fontSize: 11,
                  marginTop: 4,
                  fontFamily: FONT_FAMILY.InterMedium,
                  textAlign: "center",
                }}
              >
                {likesCount}
              </Text>
            )}
          </Pressable>
          <Pressable
            onPress={() => item?.id && openComments(item.id)}
            style={{ alignItems: "center" }}
          >
            <Image source={icons.chatBubble} style={size({ size: 26 })} />
          </Pressable>
          <Pressable>
            <Image source={icons.share} style={size({ size: 26 })} />
          </Pressable>
        </View>
        <View style={{ paddingHorizontal: 28 }}>
          <BlurView
            tint="dark"
            intensity={20}
            style={{
              paddingHorizontal: 14,
              paddingVertical: 8,
              borderRadius: 20,
              backgroundColor: Palette.glass,
              overflow: "hidden",
            }}
            experimentalBlurMethod={
              Platform.OS !== "ios" ? "dimezisBlurView" : "none"
            }
          >
            {alignedWords?.length > 0 ? (
              <KaraokeLyrics
                alignedWords={alignedWords}
                currentTimeS={currentTimeS}
              />
            ) : (
              <Text
                style={{
                  fontSize: 12,
                  color: Palette.white,
                  fontFamily: FONT_FAMILY.InterRegular,
                }}
              >
                {item?.title || "Description chanson"}
              </Text>
            )}
          </BlurView>
        </View>
      </View>
    </View>
  );
};

const Playbacks = () => {
  const [activeIndex, setActiveIndex] = useState(0);
  const userCache = useRef(new Map());
  const { getUserByUid } = useUser() || {};
  const isFocused = useIsFocused();
  const { data: playbacks = [], loadMore } = useDataFromRef({
    ref: projectsRef.where("playbackUrl", "!=", null),
    simpleRef: false,
    listener: false,
    usePagination: true,
    batchSize: 6,
  });

  const onSnap = useCallback(
    (index) => {
      setActiveIndex(index);
      // Pré-charge la suite 6 par 6
      if (index >= (playbacks?.length || 0) - 6) {
        loadMore?.();
      }
    },
    [playbacks?.length, loadMore]
  );

  return (
    <View style={{ flex: 1, backgroundColor: "black" }}>
      <Carousel
        data={playbacks}
        vertical
        height={responsiveHeight(100)}
        pagingEnabled
        windowSize={5}
        onSnapToItem={onSnap}
        renderItem={({ item, index }) => (
          <PlaybackItem
            key={item?.id || index}
            item={item}
            userCache={userCache}
            getUserByUid={getUserByUid}
            isActive={isFocused && index === activeIndex}
          />
        )}
      />
    </View>
  );
};

export default Playbacks;
