"use client";

import Link from "next/link";
import { useEffect, useRef, useState } from "react";
import supabase from "../../utils/supabase/client";
import { useAudio } from "./AudioContext";

function RadioPlaybarInner({
  currentSong,
  radioId,
  customTogglePlayPause,
}: {
  currentSong: any;
  radioId: string;
  customTogglePlayPause?: () => void;
}) {
  const { isPlaying, audioRef, togglePlayPause } = useAudio();
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);
  const [waveform, setWaveform] = useState<number[] | null>(null);
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [isSeeking, setIsSeeking] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  const [isLeader, setIsLeader] = useState(false);
  const [currentUserId, setCurrentUserId] = useState<string | null>(null);
  const [isSettingLeader, setIsSettingLeader] = useState(false);
  const [nextClipId, setNextClipId] = useState<string | null>(null);
  const [hasTriggeredGenerate, setHasTriggeredGenerate] = useState(false);
  const [isGenerating, setIsGenerating] = useState(false);

  // Use custom toggle function if provided, otherwise use default
  const handleTogglePlayPause = customTogglePlayPause || togglePlayPause;

  // Get current user ID
  useEffect(() => {
    supabase.auth.getSession().then(({ data }) => {
      setCurrentUserId(data.session?.user?.id || null);
    });
  }, []);

  // Check if current user is the leader and get next_clip_id
  useEffect(() => {
    if (!radioId || !currentUserId) return;

    const checkLeaderStatus = async () => {
      const { data, error } = await supabase
        .from("room_status")
        .select("leader_user_id, next_clip_id")
        .eq("radio_room_id", radioId)
        .single();

      if (!error && data) {
        setIsLeader(data.leader_user_id === currentUserId);
        setNextClipId(data.next_clip_id);
      }
    };

    checkLeaderStatus();

    // Listen for broadcast updates to sync state
    const channel = supabase
      .channel(`room:${radioId}:playbar`)
      .on("broadcast", { event: "*" }, (payload) => {
        // Re-fetch room status when there are updates
        checkLeaderStatus();
      })
      .subscribe();

    return () => {
      supabase.removeChannel(channel);
    };
  }, [radioId, currentUserId]);

  // Start song from beginning when currentSong changes
  useEffect(() => {
    if (audioRef.current && currentSong) {
      audioRef.current.currentTime = 0;
      setHasTriggeredGenerate(false); // Reset generate trigger for new song
    }
  }, [currentSong?.id, audioRef]);

  // Auto-generate next clip when leader reaches halfway point
  useEffect(() => {
    if (
      !isLeader ||
      !audioRef.current ||
      !duration ||
      hasTriggeredGenerate ||
      nextClipId ||
      isGenerating
    ) {
      return;
    }

    const halfwayPoint = duration / 2;

    if (currentTime >= halfwayPoint) {
      handleAutoGenerate();
    }
  }, [
    currentTime,
    duration,
    isLeader,
    hasTriggeredGenerate,
    nextClipId,
    isGenerating,
  ]);

  // Handle song end and transition to next clip
  useEffect(() => {
    const audio = audioRef.current;
    if (!audio || !isLeader) return;

    const handleSongEnd = async () => {
      if (nextClipId) {
        try {
          // Update room status to transition to next clip
          const { error } = await supabase
            .from("room_status")
            .update({
              current_clip_id: nextClipId,
              current_clip_started_at: new Date().toISOString(),
              next_clip_id: null,
            })
            .eq("radio_room_id", radioId);

          if (!error) {
            setNextClipId(null);
            setHasTriggeredGenerate(false);
          }
        } catch (error) {
          console.error("Failed to transition to next clip:", error);
        }
      }
    };

    audio.addEventListener("ended", handleSongEnd);
    return () => {
      audio.removeEventListener("ended", handleSongEnd);
    };
  }, [audioRef, isLeader, nextClipId, radioId]);

  const handleAutoGenerate = async () => {
    if (
      !radioId ||
      !isLeader ||
      hasTriggeredGenerate ||
      nextClipId ||
      isGenerating
    )
      return;

    setIsGenerating(true);
    setHasTriggeredGenerate(true); // Debounce: prevent multiple calls

    try {
      // Get the first prompt from the queue
      const { data: promptData, error: promptError } = await supabase
        .from("prompt_queue")
        .select("id")
        .eq("radio_room_id", radioId)
        .order("created_at", { ascending: true })
        .limit(1)
        .single();

      if (promptError || !promptData) {
        console.log("No prompts in queue for auto-generation");
        return;
      }

      // Call the generate function
      const { data, error } = await supabase.functions.invoke("generate_clip", {
        body: { room_id: radioId, prompt_id: promptData.id },
      });

      if (error) throw new Error(error.message || "Failed to generate");

      const newClipId = data?.ids?.[0];
      if (newClipId) {
        // Update room_status with the new next_clip_id
        const { error: updateError } = await supabase
          .from("room_status")
          .update({ next_clip_id: newClipId })
          .eq("radio_room_id", radioId);

        if (!updateError) {
          setNextClipId(newClipId);
        } else {
          throw new Error(
            updateError.message || "Failed to update next_clip_id"
          );
        }
      }
    } catch (error) {
      console.error("Auto-generation failed:", error);
      setHasTriggeredGenerate(false); // Reset on error so it can be retried
    } finally {
      setIsGenerating(false);
    }
  };

  const handleBecomeLeader = async () => {
    if (!radioId || !currentUserId || isLeader || isSettingLeader) return;

    setIsSettingLeader(true);
    try {
      const { error } = await supabase
        .from("room_status")
        .update({ leader_user_id: currentUserId })
        .eq("radio_room_id", radioId);

      if (!error) {
        setIsLeader(true);
      }
    } catch (error) {
      console.error("Failed to become leader:", error);
    } finally {
      setIsSettingLeader(false);
    }
  };

  const handleNext = async () => {
    if (!isLeader) return;

    if (nextClipId) {
      // Transition to existing next clip
      try {
        const { error } = await supabase
          .from("room_status")
          .update({
            current_clip_id: nextClipId,
            current_clip_started_at: new Date().toISOString(),
            next_clip_id: null,
          })
          .eq("radio_room_id", radioId);

        if (!error) {
          setNextClipId(null);
          setHasTriggeredGenerate(false);
        }
      } catch (error) {
        console.error("Failed to transition to next clip:", error);
      }
    } else {
      // Generate new clip and immediately switch to it
      setIsGenerating(true);
      try {
        // Get the first prompt from the queue
        const { data: promptData, error: promptError } = await supabase
          .from("prompt_queue")
          .select("id")
          .eq("radio_room_id", radioId)
          .order("created_at", { ascending: true })
          .limit(1)
          .single();

        if (promptError || !promptData) {
          console.log("No prompts in queue for generation");
          return;
        }

        // Call the generate function
        const { data, error } = await supabase.functions.invoke(
          "generate_clip",
          {
            body: { room_id: radioId, prompt_id: promptData.id },
          }
        );

        if (error) throw new Error(error.message || "Failed to generate");

        const newClipId = data?.ids?.[0];
        if (newClipId) {
          // Immediately update current_clip_id instead of next_clip_id
          const { error: updateError } = await supabase
            .from("room_status")
            .update({
              current_clip_id: newClipId,
              current_clip_started_at: new Date().toISOString(),
              next_clip_id: null,
            })
            .eq("radio_room_id", radioId);

          if (updateError) {
            throw new Error(
              updateError.message || "Failed to update current clip"
            );
          }

          setHasTriggeredGenerate(false);
        }
      } catch (error) {
        console.error("Generate and switch failed:", error);
      } finally {
        setIsGenerating(false);
      }
    }
  };

  // Fetch/generate waveform data when song changes
  useEffect(() => {
    if (!currentSong || !currentSong.audio_url) {
      setWaveform(null);
      return;
    }
    let cancelled = false;
    async function getWaveform() {
      try {
        const ctx = new (window.AudioContext ||
          (window as any).webkitAudioContext)();
        const res = await fetch(currentSong.audio_url);
        const arrayBuffer = await res.arrayBuffer();
        const audioBuffer = await ctx.decodeAudioData(arrayBuffer);
        const raw = audioBuffer.getChannelData(0);
        const samples = 80;
        const blockSize = Math.floor(raw.length / samples);
        const waveformData = Array(samples)
          .fill(0)
          .map((_, i) => {
            let sum = 0;
            for (let j = 0; j < blockSize; j++) {
              sum += Math.abs(raw[i * blockSize + j] || 0);
            }
            return sum / blockSize;
          });
        if (!cancelled) setWaveform(waveformData);
      } catch (e) {
        setWaveform(null);
      }
    }
    getWaveform();
    return () => {
      cancelled = true;
    };
  }, [currentSong?.audio_url]);

  // Sync current time and duration
  useEffect(() => {
    const audio = audioRef.current;
    if (!audio) return;
    const updateTime = () => setCurrentTime(audio.currentTime);
    const updateDuration = () => setDuration(audio.duration);
    const handleLoadStart = () => setIsLoading(true);
    const handleLoadedMetadata = () => setIsLoading(false);
    audio.addEventListener("timeupdate", updateTime);
    audio.addEventListener("loadedmetadata", updateDuration);
    audio.addEventListener("loadstart", handleLoadStart);
    audio.addEventListener("loadedmetadata", handleLoadedMetadata);
    return () => {
      audio.removeEventListener("timeupdate", updateTime);
      audio.removeEventListener("loadedmetadata", updateDuration);
      audio.removeEventListener("loadstart", handleLoadStart);
      audio.removeEventListener("loadedmetadata", handleLoadedMetadata);
    };
  }, [audioRef]);

  // Helper: is duration unknown/streaming?
  const isStreaming = !duration || isNaN(duration) || duration === Infinity;
  const seekDuration = isStreaming ? 240 : duration; // 4min fallback

  // Draw waveform (mirrored and full height)
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas || !waveform) return;
    const ctx = canvas.getContext("2d");
    if (!ctx) return;
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    const w = canvas.width;
    const h = canvas.height;
    const barWidth = w / waveform.length;
    const barActualWidth = barWidth * 0.8;
    waveform.forEach((v, i) => {
      const x = i * barWidth;
      const barHeight = v * h * 1.15;
      const barX = x + (barWidth - barActualWidth) / 2;
      ctx.fillStyle = "#fff";
      ctx.globalAlpha = 0.7;
      // Top half
      ctx.fillRect(barX, h / 2 - barHeight, barActualWidth, barHeight);
      // Bottom half (mirrored)
      ctx.fillRect(barX, h / 2, barActualWidth, barHeight);
    });
    // Draw playhead
    if (duration > 0) {
      const playheadX = (currentTime / duration) * w;
      ctx.globalAlpha = 1;
      ctx.fillStyle = "#1F8BFF";
      ctx.fillRect(playheadX - 1, 0, 3, h);
    }
  }, [waveform, currentTime, duration]);

  // Seek on click/drag
  const handleSeek = (e: React.MouseEvent<HTMLCanvasElement, MouseEvent>) => {
    if (!audioRef.current || !seekDuration) return;
    const rect = (e.target as HTMLCanvasElement).getBoundingClientRect();
    const x = e.clientX - rect.left;
    const percent = Math.max(0, Math.min(1, x / rect.width));
    const newTime = percent * seekDuration;
    audioRef.current.currentTime = newTime;
    setCurrentTime(newTime);
  };

  // Drag seek
  const handleMouseDown = (
    e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
  ) => {
    setIsSeeking(true);
    handleSeek(e);
  };
  const handleMouseMove = (
    e: React.MouseEvent<HTMLCanvasElement, MouseEvent>
  ) => {
    if (isSeeking) handleSeek(e);
  };
  const handleMouseUp = () => setIsSeeking(false);

  const formatTime = (time: number) => {
    const minutes = Math.floor(time / 60);
    const seconds = Math.floor(time % 60);
    return `${minutes}:${seconds.toString().padStart(2, "0")}`;
  };

  return (
    <div className="fixed bottom-4 left-1/2 transform -translate-x-1/2 w-full max-w-[960px] mx-4 bg-gray-500/30 backdrop-blur-2xl border border-white/[.15] dark:border-white/[.15] rounded-[40px] p-4 shadow-[0_8px_32px_0_rgba(0,0,0,0.15)] dark:shadow-[0_8px_32px_0_rgba(0,0,0,0.3)] z-50">
      <div className="flex items-center gap-4">
        {/* Play/Pause Button */}
        <button
          onClick={handleTogglePlayPause}
          className="w-12 h-12 rounded-full bg-foreground text-background flex items-center justify-center hover:bg-[#383838] dark:hover:bg-[#ccc] transition-colors"
        >
          {isPlaying ? (
            <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
              <path d="M6 4h4v16H6V4zm8 0h4v16h-4V4z" />
            </svg>
          ) : (
            <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
              <path d="M8 5v14l11-7z" />
            </svg>
          )}
        </button>

        {/* Next Button */}
        {isLeader && (
          <button
            onClick={handleNext}
            disabled={isGenerating}
            className="w-12 h-12 rounded-full bg-gray-700 hover:bg-gray-600 disabled:bg-gray-800 disabled:cursor-not-allowed text-white flex items-center justify-center transition-colors"
            title={nextClipId ? "Go to next clip" : "Generate and go to next"}
          >
            {isGenerating ? (
              <div className="w-4 h-4 animate-spin border-2 border-white border-t-transparent rounded-full"></div>
            ) : (
              <svg
                width="16"
                height="16"
                viewBox="0 0 24 24"
                fill="currentColor"
              >
                <path d="M6 4l12 8-12 8V4z M18 4h2v16h-2V4z" />
              </svg>
            )}
          </button>
        )}

        {/* Leader Button */}
        <button
          onClick={handleBecomeLeader}
          disabled={isLeader || isSettingLeader}
          className={`w-12 h-12 rounded-full flex items-center justify-center transition-colors ${
            isLeader
              ? "bg-yellow-500 text-white"
              : "bg-gray-600 hover:bg-gray-500 text-white"
          } ${
            isLeader || isSettingLeader
              ? "cursor-not-allowed"
              : "cursor-pointer"
          }`}
          title={isLeader ? "You are the leader" : "Become leader"}
        >
          {isSettingLeader ? (
            <div className="w-4 h-4 animate-spin border-2 border-white border-t-transparent rounded-full"></div>
          ) : (
            <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
              <path d="M12 2L14.09 8.26L20 9L15 14.74L16.18 21.02L12 17.77L7.82 21.02L9 14.74L4 9L9.91 8.26L12 2Z" />
            </svg>
          )}
        </button>

        {/* Generation Status Indicator */}
        {isLeader && (
          <div className="flex items-center gap-2">
            {isGenerating && (
              <div className="flex items-center gap-1 px-2 py-1 bg-blue-500/20 rounded-full">
                <div className="w-3 h-3 animate-spin border-2 border-blue-400 border-t-transparent rounded-full"></div>
                <span className="text-xs text-blue-400">Generating...</span>
              </div>
            )}
            {nextClipId && !isGenerating && (
              <div className="flex items-center gap-1 px-2 py-1 bg-green-500/20 rounded-full">
                <div className="w-3 h-3 bg-green-400 rounded-full"></div>
                <span className="text-xs text-green-400">Next ready</span>
              </div>
            )}
          </div>
        )}

        {/* Album Art */}
        <div className="w-10 h-10 rounded-lg overflow-hidden bg-black/[.05] dark:bg-white/[.05] flex-shrink-0">
          {currentSong.image_url ? (
            <img
              src={currentSong.image_url}
              alt={currentSong.title}
              className="w-full h-full object-cover"
            />
          ) : (
            <div className="w-full h-full flex items-center justify-center text-foreground/30">
              <svg
                width="20"
                height="20"
                viewBox="0 0 24 24"
                fill="currentColor"
              >
                <path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z" />
              </svg>
            </div>
          )}
        </div>

        {/* Song Info */}
        <div className="flex-1 min-w-0">
          <div className="text-sm font-medium text-foreground truncate">
            {currentSong.title}
          </div>
          {currentSong.handle ? (
            <Link href={`/@${currentSong.handle}`}>
              <div className="text-xs text-foreground/60 truncate hover:text-blue-500 transition-colors cursor-pointer">
                {currentSong.display_name}
              </div>
            </Link>
          ) : (
            <div className="text-xs text-foreground/60 truncate">
              {currentSong.display_name}
            </div>
          )}
        </div>

        {/* Waveform Progress Bar */}
        <div className="flex-1 max-w-xs flex flex-col items-center">
          <div className="flex items-center w-full">
            <span className="text-xs text-foreground/60 mr-2 whitespace-nowrap">
              {formatTime(currentTime)}
            </span>
            <div className="flex-1 flex justify-center">
              <canvas
                ref={canvasRef}
                width={400}
                height={32}
                className="w-full h-8 cursor-pointer"
                style={{ display: "block" }}
                onMouseDown={handleMouseDown}
                onMouseMove={handleMouseMove}
                onMouseUp={handleMouseUp}
                onMouseLeave={handleMouseUp}
              />
            </div>
            <span className="text-xs text-foreground/60 ml-2 whitespace-nowrap">
              {isStreaming || isLoading ? (
                <span className="inline-block align-middle w-4 h-4 animate-spin border-2 border-gray-300 border-t-blue-500 rounded-full"></span>
              ) : (
                formatTime(duration)
              )}
            </span>
          </div>
        </div>
      </div>
    </div>
  );
}

export default function RadioPlaybar({
  radioId,
  customTogglePlayPause,
}: {
  radioId: string;
  customTogglePlayPause?: () => void;
}) {
  const { currentSong } = useAudio();
  if (!currentSong) return null;
  return (
    <RadioPlaybarInner
      currentSong={currentSong}
      radioId={radioId}
      customTogglePlayPause={customTogglePlayPause}
    />
  );
}
