import { useEffect, useCallback, useState, useMemo } from "react";
import { useParams, useNavigate } from "react-router-dom";
import { ArrowLeft } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { useAppStore } from "@/stores/app-store";
import { usePlaybackStore } from "@/stores/playback-store";
import { useRecordingStore } from "@/stores/recording-store";
import { ParticleRenderer } from "@/features/playback/particle-renderer";
import { PlaybackPageIndicator } from "@/features/playback/playback-page-indicator";
import { ReplyIndicator } from "@/features/recording/reply-indicator";
import { TextComposeOverlay } from "@/features/recording/text-compose-overlay";
import { RecordingOverlay } from "@/features/recording/recording-overlay";
import { useRecorder } from "@/features/recording/use-recorder";

export function StreamPlayerPage() {
  const { streamId } = useParams<{ streamId: string }>();
  const navigate = useNavigate();
  const networks = useAppStore((s) => s.networks);
  const [composingText, setComposingText] = useState(false);
  const [showRecordingOverlay, setShowRecordingOverlay] = useState(false);

  const particles = usePlaybackStore((s) => s.particles);
  const currentIndex = usePlaybackStore((s) => s.currentIndex);
  const initStream = usePlaybackStore((s) => s.initStream);
  const next = usePlaybackStore((s) => s.next);
  const prev = usePlaybackStore((s) => s.prev);
  const goTo = usePlaybackStore((s) => s.goTo);
  const reset = usePlaybackStore((s) => s.reset);
  const pause = usePlaybackStore((s) => s.pause);
  const resume = usePlaybackStore((s) => s.resume);

  const networkForStream = useMemo(() => {
    return networks.find((n) =>
      n.streams.some((s) => s.id === streamId),
    );
  }, [networks, streamId]);

  const stream = useMemo(() => {
    if (!networkForStream) return null;
    return networkForStream.streams.find((s) => s.id === streamId) || null;
  }, [networkForStream, streamId]);

  const { startRecording, stopRecording, cancelRecording, confirmSend } =
    useRecorder(streamId ?? null, networkForStream?.id ?? null);

  useEffect(() => {
    if (!stream) return;

    const firstUnseenIndex = stream.particles.findIndex((p) => !p.seen);
    const startIndex =
      firstUnseenIndex >= 0
        ? firstUnseenIndex
        : Math.max(0, stream.particles.length - 1);

    initStream(stream.id, stream.particles, startIndex);

    return () => {
      reset();
    };
  }, [stream?.id]); // eslint-disable-line react-hooks/exhaustive-deps

  const handleRecordingOverlayClose = useCallback(() => {
    setShowRecordingOverlay(false);
    resume();
  }, [resume]);

  // Unified keyboard handling
  const handleKeyDown = useCallback(
    (e: KeyboardEvent) => {
      if (composingText) return;

      const recStatus = useRecordingStore.getState().status;

      // Q/Esc during recording or reviewing: cancel immediately
      if (
        (e.key === "q" || e.key === "Q" || e.key === "Escape") &&
        (recStatus === "recording" || recStatus === "reviewing")
      ) {
        e.preventDefault();
        cancelRecording();
        setShowRecordingOverlay(false);
        resume();
        return;
      }

      // Enter or backtick during reviewing: send
      if (
        (e.key === "Enter" || e.key === "`") &&
        recStatus === "reviewing"
      ) {
        e.preventDefault();
        confirmSend();
        return;
      }

      // Block navigation while recording/uploading
      if (recStatus === "recording" || recStatus === "uploading") {
        return;
      }

      if (e.key === "`" && !e.repeat) {
        e.preventDefault();
        pause();
        startRecording();
        setShowRecordingOverlay(true);
      } else if (e.key === "ArrowRight" || e.key === "ArrowDown") {
        e.preventDefault();
        next();
      } else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
        e.preventDefault();
        prev();
      } else if (e.key === "Escape") {
        navigate("/");
      } else if (e.key === "t" || e.key === "T") {
        e.preventDefault();
        setComposingText(true);
      }
    },
    [
      composingText,
      next,
      prev,
      navigate,
      pause,
      resume,
      startRecording,
      cancelRecording,
      confirmSend,
    ],
  );

  const handleKeyUp = useCallback(
    (e: KeyboardEvent) => {
      if (composingText) return;

      const recStatus = useRecordingStore.getState().status;

      if (e.key === "`" && recStatus === "recording") {
        e.preventDefault();
        stopRecording();
        // Transitions to reviewing — overlay stays open
      }
    },
    [composingText, stopRecording],
  );

  useEffect(() => {
    window.addEventListener("keydown", handleKeyDown);
    window.addEventListener("keyup", handleKeyUp);
    return () => {
      window.removeEventListener("keydown", handleKeyDown);
      window.removeEventListener("keyup", handleKeyUp);
    };
  }, [handleKeyDown, handleKeyUp]);

  if (!stream) {
    return (
      <div className="flex h-screen items-center justify-center">
        <p className="text-muted-foreground text-sm">Stream not found</p>
      </div>
    );
  }

  if (particles.length === 0) {
    return (
      <div className="flex h-screen flex-col bg-black text-white">
        {/* Top overlay */}
        <div className="pointer-events-none absolute top-0 right-0 left-0 z-10 px-2 pt-2">
          <div className="pointer-events-auto inline-flex">
            <Button
              variant="ghost"
              size="icon"
              className="rounded-full bg-black/30 text-white backdrop-blur-sm hover:bg-black/50"
              onClick={() => navigate("/")}
            >
              <ArrowLeft className="h-4 w-4" />
            </Button>
          </div>
        </div>
        <div className="flex flex-1 items-center justify-center">
          <p className="text-muted-foreground text-sm">
            No particles yet. Hold ` to record the first one.
          </p>
        </div>
        <div className="absolute right-0 bottom-0 left-0 z-10 flex items-center justify-between px-4 py-3">
          <span className="text-xs font-medium text-white/70">
            {stream.name}
          </span>
          <ReplyIndicator />
        </div>

        {composingText && streamId && (
          <TextComposeOverlay
            streamId={streamId}
            onClose={() => setComposingText(false)}
          />
        )}

        {showRecordingOverlay && (
          <RecordingOverlay onClose={handleRecordingOverlayClose} />
        )}
      </div>
    );
  }

  const currentParticle = particles[currentIndex];

  return (
    <div className="relative h-screen bg-black text-white">
      {/* Particle content — fills entire viewport */}
      <div className="absolute inset-0">
        {currentParticle && (
          <ParticleRenderer particle={currentParticle} />
        )}
      </div>

      {/* Top overlay: progress bars + back button */}
      <div className="pointer-events-none absolute top-0 right-0 left-0 z-10">
        <div className="pointer-events-auto">
          <PlaybackPageIndicator
            total={particles.length}
            current={currentIndex}
            onGoTo={goTo}
          />
        </div>
        <div className="pointer-events-auto mt-1 inline-flex px-2">
          <Button
            variant="ghost"
            size="icon"
            className="rounded-full bg-black/30 text-white backdrop-blur-sm hover:bg-black/50"
            onClick={() => navigate("/")}
          >
            <ArrowLeft className="h-4 w-4" />
          </Button>
        </div>
      </div>

      {/* Top center overlay for particle author avatar and name */}
      <div className="absolute top-0 left-1/2 transform -translate-x-1/2 z-10 mt-3 rounded-full bg-white/10 px-1 py-1 backdrop-blur-sm">
        <div className="flex items-center gap-1">
          {currentParticle && (
            <Avatar size="sm">
              <AvatarFallback className="bg-white/20 text-[10px] text-white">
                {currentParticle.created_by_email
                  .split("@")[0]
                  .slice(0, 2)
                  .toUpperCase()}
              </AvatarFallback>
            </Avatar>
          )}
          <span className="min-w-0 flex-1 truncate text-xs font-medium text-white/70 pr-1">
            {currentParticle?.created_by_email.split("@")[0]}
            <span className="text-white/40"> &middot; </span>
            {stream.name}
          </span>
        </div>
      </div>

      {/* Bottom overlay: stream info + reply */}
      <div className="absolute right-0 bottom-0 left-0 z-10 flex justify-center px-3 pb-3">
        <div className="flex w-full items-center gap-2.5 rounded-full bg-black/30 px-3 py-2 backdrop-blur-sm">
          <div className="flex-1 text-left text-sm font-medium text-white/70">
            _this is a placeholder for captions_
          </div>

          <ReplyIndicator />
        </div>
      </div>

      {/* Text compose overlay */}
      {composingText && streamId && (
        <TextComposeOverlay
          streamId={streamId}
          onClose={() => setComposingText(false)}
        />
      )}

      {/* Recording overlay */}
      {showRecordingOverlay && (
        <RecordingOverlay onClose={handleRecordingOverlayClose} />
      )}
    </div>
  );
}
