import { useCallback, useEffect, useRef, useState } from "react";
import { Platform } from "react-native";
import { type SharedValue, useSharedValue } from "react-native-reanimated";
import { msToTicks, ticksToSeconds } from "@/utils/time";
import { CONTROLS_CONSTANTS } from "../constants";

// TV event handler with fallback for non-TV platforms
let useTVEventHandler: (callback: (evt: any) => void) => void;
if (Platform.isTV) {
  try {
    useTVEventHandler = require("react-native").useTVEventHandler;
  } catch {
    // Fallback for non-TV platforms
    useTVEventHandler = () => {};
  }
} else {
  // No-op hook for non-TV platforms
  useTVEventHandler = () => {};
}

interface UseRemoteControlProps {
  progress: SharedValue<number>;
  min: SharedValue<number>;
  max: SharedValue<number>;
  showControls: boolean;
  isPlaying: boolean;
  seek: (value: number) => void;
  play: () => void;
  togglePlay: () => void;
  toggleControls: () => void;
  calculateTrickplayUrl: (progressInTicks: number) => void;
  handleSeekForward: (seconds: number) => void;
  handleSeekBackward: (seconds: number) => void;
}

/**
 * Hook to manage TV remote control interactions.
 * MPV player uses milliseconds for time values.
 */
export function useRemoteControl({
  progress,
  min,
  max,
  showControls,
  isPlaying,
  seek,
  play,
  togglePlay,
  toggleControls,
  calculateTrickplayUrl,
  handleSeekForward,
  handleSeekBackward,
}: UseRemoteControlProps) {
  const remoteScrubProgress = useSharedValue<number | null>(null);
  const isRemoteScrubbing = useSharedValue(false);
  const [showRemoteBubble, setShowRemoteBubble] = useState(false);
  const [longPressScrubMode, setLongPressScrubMode] = useState<
    "FF" | "RW" | null
  >(null);
  const [isSliding, setIsSliding] = useState(false);
  const [time, setTime] = useState({ hours: 0, minutes: 0, seconds: 0 });

  const longPressTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(
    null,
  );
  // MPV uses ms
  const SCRUB_INTERVAL = CONTROLS_CONSTANTS.SCRUB_INTERVAL_MS;

  const updateTime = useCallback((progressValue: number) => {
    // Convert ms to ticks for calculation
    const progressInTicks = msToTicks(progressValue);
    const progressInSeconds = Math.floor(ticksToSeconds(progressInTicks));
    const hours = Math.floor(progressInSeconds / 3600);
    const minutes = Math.floor((progressInSeconds % 3600) / 60);
    const seconds = progressInSeconds % 60;
    setTime({ hours, minutes, seconds });
  }, []);

  // TV remote control handling (no-op on non-TV platforms)
  useTVEventHandler((evt) => {
    if (!evt) return;

    switch (evt.eventType) {
      case "longLeft": {
        setLongPressScrubMode((prev) => (!prev ? "RW" : null));
        break;
      }
      case "longRight": {
        setLongPressScrubMode((prev) => (!prev ? "FF" : null));
        break;
      }
      case "left":
      case "right": {
        isRemoteScrubbing.value = true;
        setShowRemoteBubble(true);

        const direction = evt.eventType === "left" ? -1 : 1;
        const base = remoteScrubProgress.value ?? progress.value;
        const updated = Math.max(
          min.value,
          Math.min(max.value, base + direction * SCRUB_INTERVAL),
        );
        remoteScrubProgress.value = updated;
        // Convert ms to ticks for trickplay
        const progressInTicks = msToTicks(updated);
        calculateTrickplayUrl(progressInTicks);
        updateTime(updated);
        break;
      }
      case "select": {
        if (isRemoteScrubbing.value && remoteScrubProgress.value != null) {
          progress.value = remoteScrubProgress.value;

          // MPV uses ms, seek expects ms
          const seekTarget = Math.max(0, remoteScrubProgress.value);

          seek(seekTarget);
          if (isPlaying) play();

          isRemoteScrubbing.value = false;
          remoteScrubProgress.value = null;
          setShowRemoteBubble(false);
        } else {
          togglePlay();
        }
        break;
      }
      case "down":
      case "up":
        // cancel scrubbing on other directions
        isRemoteScrubbing.value = false;
        remoteScrubProgress.value = null;
        setShowRemoteBubble(false);
        break;
      default:
        break;
    }

    if (!showControls) toggleControls();
  });

  useEffect(() => {
    let isActive = true;
    let seekTime = CONTROLS_CONSTANTS.LONG_PRESS_INITIAL_SEEK;

    const scrubWithLongPress = () => {
      if (!isActive || !longPressScrubMode) return;

      setIsSliding(true);
      const scrubFn =
        longPressScrubMode === "FF" ? handleSeekForward : handleSeekBackward;
      scrubFn(seekTime);
      seekTime *= CONTROLS_CONSTANTS.LONG_PRESS_ACCELERATION;

      longPressTimeoutRef.current = setTimeout(
        scrubWithLongPress,
        CONTROLS_CONSTANTS.LONG_PRESS_INTERVAL,
      );
    };

    if (longPressScrubMode) {
      isActive = true;
      scrubWithLongPress();
    }

    return () => {
      isActive = false;
      setIsSliding(false);
      if (longPressTimeoutRef.current) {
        clearTimeout(longPressTimeoutRef.current);
        longPressTimeoutRef.current = null;
      }
    };
  }, [longPressScrubMode, handleSeekForward, handleSeekBackward]);

  return {
    remoteScrubProgress,
    isRemoteScrubbing,
    showRemoteBubble,
    longPressScrubMode,
    isSliding,
    time,
  };
}
