import { useFocusEffect } from "@react-navigation/native";
import { useAudioPlayer } from "expo-audio";
import { CameraView, useCameraPermissions } from "expo-camera";
import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import { Text, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import Svg, { Circle } from "react-native-svg";
import GradientButton from "../../components/GradientButton";
import KaraokeLyrics from "../../components/KaraokeLyrics";
import MusicLandHeader from "../../components/MusicLandHeader";
import { increment, projectsRef } from "../../config/firebase";
import { Routes } from "../../navigation";
import { goBack, navigate } from "../../navigation/NavigationService";
import { gutters, Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";

const TIME_BEFORE_INCREMENT_MS = 20000; // 20s

const RecordPlayback = ({ route }) => {
  const { top, bottom } = useSafeAreaInsets();
  const { project } = route.params || {};
  const projectId = project?.id;
  const songIndex = project?.songIndex;
  // Permissions
  const [cameraPermission, requestCameraPermission] = useCameraPermissions();

  // Refs
  const cameraRef = useRef(null);
  const countdownTimerRef = useRef(null);
  const listenTimerRef = useRef(null);
  const checkSongEndRef = useRef(null);
  const stopRequestedRef = useRef(false);
  const startedRef = useRef(false); // empêche les doubles démarrages
  const countdownActiveRef = useRef(false); // évite le déclenchement avant 1er tick

  // Compteurs vues
  const listenedMsRef = useRef(0);
  const incrementDoneRef = useRef(false);

  // UI / state
  const [isPreparing, setIsPreparing] = useState(false);
  const [countdown, setCountdown] = useState(0);
  const [isRecording, setIsRecording] = useState(false);
  const [showProgress, setShowProgress] = useState(false);
  const [progressInfo, setProgressInfo] = useState({ pos: 0, dur: 0 });

  // Musique
  const songUrl = project?.songUrl || null;
  const player = useAudioPlayer(songUrl ? { uri: songUrl } : undefined);

  const musicIndex = useMemo(() => {
    const i = Number(songIndex);
    return Number.isFinite(i) && i >= 0 ? i : 0;
  }, [songIndex]);

  const alignedWords = useMemo(() => {
    const ts = project?.musicTimestamps?.[musicIndex];

    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),
    }));
  }, [project?.musicTimestamps, musicIndex]);

  // Build line groups to display line-by-line
  const lines = useMemo(() => {
    const out = [];
    let buf = [];
    let start = null;
    const clean = (txt) =>
      String(txt || "")
        .replace(/\s+/g, " ")
        .trim();
    const isSentenceEnd = (txt) => /[.!?]$/.test((txt || "").trim());
    const isSectionTag = (txt) =>
      /^\s*\[[^\]]+\]\s*$/i.test((txt || "").trim());
    for (let i = 0; i < alignedWords.length; i++) {
      const w = alignedWords[i];
      const original = String(w.word || "");
      const textNoNewline = original.replace(/\n/g, " ");
      const gapToNext =
        i < alignedWords.length - 1
          ? Math.max(0, alignedWords[i + 1].startS - w.endS)
          : 0;

      // If buffer empty, mark start
      if (buf.length === 0) start = w.startS;

      // Section tag becomes its own line
      if (isSectionTag(textNoNewline)) {
        const joined = clean(textNoNewline);
        if (joined)
          out.push({ text: joined, startS: start ?? w.startS, endS: w.endS });
        buf = [];
        start = null;
        continue;
      }

      buf.push(textNoNewline);

      const eolByNewline = /\n/.test(original);
      const eolByPause = gapToNext >= 0.6;
      const eolByPunct = isSentenceEnd(textNoNewline);
      const isLast = i === alignedWords.length - 1;

      if (eolByNewline || eolByPause || eolByPunct || isLast) {
        const joined = clean(buf.join(" "));
        if (joined)
          out.push({ text: joined, startS: start ?? w.startS, endS: w.endS });
        buf = [];
        start = null;
      }
    }
    return out;
  }, [alignedWords]);
  // console.log("alignedWords:", alignedWords);
  useEffect(() => {
    listenedMsRef.current = 0;
    incrementDoneRef.current = false;
  }, [songUrl]);

  // Poll player -> progress ring
  useEffect(() => {
    if (!player) return;
    const id = setInterval(() => {
      try {
        const dur = (player?.duration || 0) * 1000;
        const pos = (player?.currentTime || 0) * 1000;
        setProgressInfo({ pos, dur });
      } catch (_) {}
    }, 250);
    return () => clearInterval(id);
  }, [player]);

  // Compute current line index from playback time
  const currentTimeS = (progressInfo?.pos || 0) / 1000;
  const currentLineIdx = useMemo(() => {
    if (!lines || lines.length === 0) return -1;
    for (let i = 0; i < lines.length; i++) {
      const L = lines[i];
      if (currentTimeS >= L.startS && currentTimeS <= L.endS) return i;
    }
    if (currentTimeS > (lines[lines.length - 1]?.endS || 0))
      return lines.length - 1;
    return -1;
  }, [lines, currentTimeS]);

  // Permissions au mount + cleanup
  useEffect(() => {
    (async () => {
      try {
        if (!cameraPermission?.granted) await requestCameraPermission();
      } catch (_) {}
    })();
    return () => {
      try {
        if (countdownTimerRef.current) clearInterval(countdownTimerRef.current);
        if (listenTimerRef.current) clearInterval(listenTimerRef.current);
        if (checkSongEndRef.current) clearInterval(checkSongEndRef.current);
        countdownTimerRef.current = null;
        listenTimerRef.current = null;
        checkSongEndRef.current = null;
      } catch (_) {}
    };
  }, []); // eslint-disable-line react-hooks/exhaustive-deps

  // Reset complet
  const resetSession = useCallback(async () => {
    try {
      if (countdownTimerRef.current) {
        clearInterval(countdownTimerRef.current);
        countdownTimerRef.current = null;
      }
      if (listenTimerRef.current) {
        clearInterval(listenTimerRef.current);
        listenTimerRef.current = null;
      }
      if (checkSongEndRef.current) {
        clearInterval(checkSongEndRef.current);
        checkSongEndRef.current = null;
      }

      startedRef.current = false;
      stopRequestedRef.current = false;
      countdownActiveRef.current = false;
      listenedMsRef.current = 0;
      incrementDoneRef.current = false;

      setIsPreparing(false);
      setIsRecording(false);
      setShowProgress(false);
      setCountdown(0);

      if (player) {
        try {
          if (player.playing) await player.pause?.();
          await player.seekTo?.(0);
        } catch (_) {}
      }
    } catch (_) {}
  }, [player]);

  useFocusEffect(
    useCallback(() => {
      void resetSession();
      return () => {};
    }, [resetSession])
  );

  // Lancer le compte à rebours (le tick décrémente uniquement)
  const startCountdownThenRecord = async () => {
    if (!songUrl) return;
    await resetSession();
    setIsPreparing(true);
    setShowProgress(false);
    setCountdown(5);

    // On démarre l'intervalle puis on active le flag
    if (countdownTimerRef.current) {
      clearInterval(countdownTimerRef.current);
      countdownTimerRef.current = null;
    }
    countdownTimerRef.current = setInterval(() => {
      setCountdown((c) => Math.max(0, c - 1));
    }, 1000);
    countdownActiveRef.current = true;
  };

  // Quand le compteur a réellement démarré ET atteint 0, on démarre
  useEffect(() => {
    if (!isPreparing) return;
    if (!countdownActiveRef.current) return; // évite l'auto-start

    if (countdown === 0 && !startedRef.current) {
      startedRef.current = true;
      if (countdownTimerRef.current) {
        clearInterval(countdownTimerRef.current);
        countdownTimerRef.current = null;
      }
      countdownActiveRef.current = false;
      // Bascule après rendu de la frame courante
      requestAnimationFrame(() => {
        setIsPreparing(false);
        setShowProgress(true);
        void startRecordingWithMusic();
      });
    }
  }, [countdown, isPreparing]);

  const startRecordingWithMusic = async () => {
    try {
      stopRequestedRef.current = false;
      listenedMsRef.current = 0;
      incrementDoneRef.current = false;

      setIsRecording(true);
      setShowProgress(true);
      const recordPromise = cameraRef.current?.recordAsync?.({
        mute: true,
        maxDuration: 600,
      });

      if (player && songUrl) {
        try {
          await player.seekTo?.(0);
        } catch (_) {}
        await player.play?.();
      }

      // Incrément des vues
      if (!listenTimerRef.current && project?.id) {
        listenTimerRef.current = setInterval(async () => {
          try {
            if (player?.playing) {
              listenedMsRef.current += 500;
              if (
                !incrementDoneRef.current &&
                listenedMsRef.current >= TIME_BEFORE_INCREMENT_MS
              ) {
                incrementDoneRef.current = true;
                try {
                  await projectsRef
                    .doc(project.id)
                    .set({ views: increment(1) }, { merge: true });
                } catch (_) {}
              }
            }
          } catch (_) {}
        }, 500);
      }

      // Fin du morceau -> stop recording
      if (!checkSongEndRef.current) {
        checkSongEndRef.current = setInterval(() => {
          try {
            if (!player) return;
            const duration = (player?.duration || 0) * 1000;
            const currentTime = (player?.currentTime || 0) * 1000;
            if (
              (!player.playing && !stopRequestedRef.current) ||
              (duration > 0 && currentTime >= duration - 600)
            ) {
              stopRequestedRef.current = true;
              if (checkSongEndRef.current) {
                clearInterval(checkSongEndRef.current);
                checkSongEndRef.current = null;
              }
              try {
                cameraRef.current?.stopRecording?.();
              } catch (_) {}
            }
          } catch (_) {}
        }, 500);
      }

      const video = await recordPromise;

      if (checkSongEndRef.current) {
        clearInterval(checkSongEndRef.current);
        checkSongEndRef.current = null;
      }
      try {
        if (player?.playing) await player.pause?.();
      } catch (_) {}
      if (listenTimerRef.current) {
        clearInterval(listenTimerRef.current);
        listenTimerRef.current = null;
      }

      setIsRecording(false);
      setShowProgress(false);

      if (video?.uri)
        navigate(Routes.RecordedPlayback, { videoUri: video.uri, project });
      else navigate(Routes.RecordedPlayback, { project });
    } catch (e) {
      console.log("RecordPlayback error:", e);
      setIsRecording(false);
      setIsPreparing(false);
      setShowProgress(false);
      if (listenTimerRef.current) {
        clearInterval(listenTimerRef.current);
        listenTimerRef.current = null;
      }
      if (checkSongEndRef.current) {
        clearInterval(checkSongEndRef.current);
        checkSongEndRef.current = null;
      }
    }
  };

  const permissionsGranted = !!cameraPermission?.granted;

  return (
    <View style={{ flex: 1 }}>
      <CameraView
        ref={cameraRef}
        style={{ flex: 1 }}
        facing="front"
        mode="video"
      >
        <View
          style={{
            paddingHorizontal: gutters,
            paddingTop: top,
            flex: 1,
            paddingBottom: gutters * 2,
          }}
        >
          <MusicLandHeader progress={9} onPressBack={goBack} />

          <View style={{ flex: 1, marginTop: 11 }}>
            {/* Overlay de compte à rebours : on affiche 5→1 pour éviter l'effet visuel à 1 */}
            {isPreparing && countdown >= 1 && !showProgress && (
              <View
                style={{
                  position: "absolute",
                  top: 0,
                  left: 0,
                  right: 0,
                  bottom: 0,
                  alignItems: "center",
                  justifyContent: "center",
                }}
              >
                <Text
                  style={{
                    fontSize: 72,
                    color: Palette.white,
                    fontFamily: FONT_FAMILY.HelveticaNeueBold,
                  }}
                >
                  {countdown}
                </Text>
              </View>
            )}

            {/* Permission prompt */}
            {!permissionsGranted && (
              <View
                style={{
                  position: "absolute",
                  left: 0,
                  right: 0,
                  bottom: 0,
                  padding: gutters,
                }}
              >
                <GradientButton
                  title="Autoriser la caméra"
                  onPress={async () => {
                    try {
                      if (!cameraPermission?.granted)
                        await requestCameraPermission();
                    } catch (_) {}
                  }}
                />
              </View>
            )}
          </View>

          {/* Start button */}
          {permissionsGranted && !isPreparing && !isRecording && (
            <GradientButton
              title="Lancer ma musique"
              containerStyle={{ width: "80%", alignSelf: "center" }}
              disabled={!songUrl}
              onPress={startCountdownThenRecord}
            />
          )}

          {/* Progress circulaire */}
          {permissionsGranted && (isRecording || showProgress) && (
            <View
              style={{
                position: "absolute",
                left: 0,
                right: 0,
                bottom: gutters,
                alignItems: "center",
                justifyContent: "center",
              }}
            >
              <View
                style={{
                  width: 100,
                  height: 100,
                  borderRadius: 105,
                  alignItems: "center",
                  justifyContent: "center",
                }}
              >
                <ProgressRing
                  size={100}
                  strokeWidth={8}
                  progress={
                    progressInfo.dur
                      ? Math.min(1, (progressInfo.pos || 0) / progressInfo.dur)
                      : 0
                  }
                />
                <View
                  style={{
                    position: "absolute",
                    width: 50,
                    height: 50,
                    borderRadius: 55,
                    backgroundColor: Palette.white,
                  }}
                />
              </View>
            </View>
          )}
        </View>
      </CameraView>
      {/* CreateLyricsHeader overlay outside of CameraView */}
      <View
        pointerEvents="box-none"
        style={{
          position: "absolute",
          left: 0,
          right: 0,
          bottom: bottom + 130,
          paddingHorizontal: gutters,
        }}
      >
        <CreateLyricsHeader>
          {(isRecording || showProgress) && alignedWords?.length > 0 ? (
            <KaraokeLyrics
              alignedWords={alignedWords}
              currentTimeS={(progressInfo?.pos || 0) / 1000}
            />
          ) : (
            <Text
              style={{
                fontSize: 16,
                color: Palette.white,
                fontFamily: FONT_FAMILY.InterMedium,
              }}
            >
              L'enregistrement de ta vidéo commencera lorsque tu lanceras ta
              musique, et s'arrêtera à la fin du morceau.
            </Text>
          )}
        </CreateLyricsHeader>
      </View>
    </View>
  );
};

// Progress ring SVG
const ProgressRing = ({ size = 50, strokeWidth = 12, progress = 0 }) => {
  const r = size / 2 - strokeWidth / 2;
  const c = 2 * Math.PI * r;
  const clamped = Math.max(0, Math.min(1, progress || 0));
  const offset = c * (1 - clamped);
  return (
    <Svg
      width={size}
      height={size}
      style={{
        transform: [{ rotate: "-90deg" }],
        backgroundColor: "#ffffff3d",
        borderRadius: 55,
      }}
    >
      <Circle
        cx={size / 2}
        cy={size / 2}
        r={r}
        stroke={Palette.white}
        strokeWidth={strokeWidth}
        strokeLinecap="round"
        strokeDasharray={`${c} ${c}`}
        strokeDashoffset={offset}
        fill="transparent"
      />
    </Svg>
  );
};

export default RecordPlayback;

// Render previous/current/next line to reduce jumpiness
const KaraokeLines = ({ lines = [], currentLineIdx = -1 }) => {
  const prev = currentLineIdx > 0 ? lines[currentLineIdx - 1]?.text : "";
  const curr = currentLineIdx >= 0 ? lines[currentLineIdx]?.text : "";
  const next =
    currentLineIdx + 1 < lines.length ? lines[currentLineIdx + 1]?.text : "";
  return (
    <View style={{ gap: 4 }}>
      {/* {prev ? (
        <Text style={{ color: "#FFFFFF99", fontSize: 14, textAlign: "center", fontFamily: FONT_FAMILY.InterMedium }}>
          {prev}
        </Text>
      ) : null} */}
      <Text
        style={{
          color: Palette.white,
          fontSize: 18,
          textAlign: "center",
          fontFamily: FONT_FAMILY.InterSemiBold,
        }}
      >
        {curr}
      </Text>
      {next ? (
        <Text
          style={{
            color: "#FFFFFF99",
            fontSize: 14,
            textAlign: "center",
            fontFamily: FONT_FAMILY.InterMedium,
          }}
        >
          {next}
        </Text>
      ) : null}
    </View>
  );
};
