"use client";

// import { Room } from "./Room";

import { useEventListener, useSend } from "@jamsocket/socketio";
import { observer } from "mobx-react-lite";

import type { ConnectResponse } from "@jamsocket/socketio";
import { SessionBackendProvider, SocketIOProvider } from "@jamsocket/socketio";

import clsx from "clsx";
import { useEffect, useMemo, useRef, useState } from "react";

const OnlineUsers = observer(() => {
  const jamState = useJamState();
  return (
    <div className="text-sm text-gray-400">
      {/* Online: <span className="text-white">You</span>
      {jamState.jam.presence > 0 && ", "} */}
      {Object.entries(jamState.jam.presence)
        .map(([id, user]) => user.username || "Anon")
        .join(", ")}
    </div>
  );
});

const EmojiBoard = ({
  username,
  onSubmit,
}: {
  username: string;
  onSubmit: (event: any) => void;
}) => {
  const musicEmojis = [
    "🎵", // musical note
    "🔥", // fire
    "💃", // dancing woman
    "🕺", // dancing man
    "👏", // clapping hands
    "❤️", // heart
    "🎸", // guitar
    "🥁", // drums
    "🎹", // piano
    "🎷", // saxophone
  ];

  const [commentInput, setCommentInput] = useState("");

  const sendEvent = useSend();

  return (
    <div className="grid grid-cols-5 gap-2 p-4">
      {musicEmojis.map((emoji, index) => (
        <button
          key={index}
          className="text-2xl p-2 hover:bg-gray-700 rounded transition-colors"
          onClick={() => {
            // TODO: Add emoji reaction handling
            const event = {
              type: "EMOJI",
              emoji: emoji,
              username: username,
              comment: "",
            };
            onSubmit(event);
            sendEvent("reaction", event);
            console.log(`Clicked ${emoji}`);
          }}
        >
          {emoji}
        </button>
      ))}
      <div className="col-span-5">
        <input
          type="text"
          placeholder="Type a comment and press Enter..."
          className="w-full text-sm p-2 rounded bg-gray-800 text-white"
          value={commentInput}
          onChange={(e) => setCommentInput(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === "Enter" && commentInput.trim()) {
              const event = {
                type: "EMOJI",
                emoji: "🔥",
                username: username,
                comment: commentInput,
              };
              sendEvent("reaction", event);
              onSubmit(event);
              setCommentInput("");
            }
          }}
        />
      </div>
    </div>
  );
};

const FloatingEmoji = ({
  emoji,
  username,
  comment,
}: {
  emoji: string;
  username: string;
  comment: string;
}) => {
  const randomX = useMemo(() => Math.random() * 50 + 25, []); // Random position from 20-80% of container width for more centered feel
  return (
    <div
      className="fixed bottom-[300px] flex items-center text-white animate-float-up pointer-events-none bg-white/80 px-3 py-1 rounded-full"
      style={{ left: `${randomX}%` }}
    >
      <span className="text-2xl mr-2">{emoji}</span>
      <div className="flex flex-col">
        <span className="text-xs text-gray-800">{username}</span>
        <span className="text-xs text-black">{comment}</span>
      </div>
    </div>
  );
};

const RoomBase = observer(() => {
  const sendEvent = useSend();

  const jamState = useJamState();
  const currentRoom = jamState.jam.rooms["test"];

  const [clipUrlInput, setClipUrlInput] = useState("");

  const [username, setUsername] = useState(
    localStorage.getItem("username") || ""
  );

  const onSubmitUsername = () => {
    localStorage.setItem("username", username);
    sendEvent("presence-set-username", { username });
  };

  useEffect(() => {
    onSubmitUsername();
  }, []);

  const addClip = (clip) => {
    sendEvent("add-clip", clip);
  };

  useEventListener<any>("add-clip", (clip) => {
    jamState.addClip(clip);
  });

  const onSubmit = async (text?: string) => {
    console.log("onSubmit", clipUrlInput);
    const clipId = (clipUrlInput || text || "").split("/").pop();
    if (!clipId) return;
    console.log(clipId);

    const data = await fetch(`/api/clip?clipId=${clipId}`);

    const clip = await data.json();
    console.log(clip);

    addClip({
      ...clip,
      submitterId: "",
      submitterUsername: username,
      url: clipUrlInput,
    });

    setClipUrlInput("");
  };

  // const resetState = useMutation(({ storage }) => {
  //   storage.get("clips").clear();
  //   storage.set("currentPlay", new LiveObject({ state: null }));
  // }, []);
  const resetState = () => {
    sendEvent("reset-state", {});
  };

  const playSong = (clip) => {
    sendEvent("play-state", {
      clip: clip,
      playTimestamp: new Date().getTime(),
      seekTime: 0,
      isPlaying: true,
    });
  };

  const pauseSong = () => {
    if (!currentRoom.playState) return;
    sendEvent("play-state", {
      ...currentRoom.playState,
      isPlaying: false,
    });
  };

  // const deleteSong = useMutation(({ storage }, index) => {
  //   storage.get("clips").delete(index);
  // }, []);

  const deleteSong = (id) => {
    sendEvent("delete-clip", id);
  };

  const audioRef = useRef<HTMLAudioElement>(null);

  useEventListener<any>("presence", (presence) => {
    jamState.setPresence(presence);
  });

  useEventListener<any>("play-state", (state) => {
    console.log("play-state", state, audioRef.current);
    jamState.setPlayState(state);
    if (audioRef.current) {
      audioRef.current.src = state.clip.audio_url;

      if (state.isPlaying) {
        audioRef.current.play();
      } else {
        audioRef.current.pause();
      }
    }
  });

  const [emojiReactions, setEmojiReactions] = useState<
    Array<{
      id: number;
      emoji: string;
      username: string;
      comment: string;
    }>
  >([]);

  const showEmoji = (event) => {
    const newReaction = {
      id: Date.now(),
      emoji: event.emoji,
      username: event.username || "Anon",
      comment: event.comment,
    };

    setEmojiReactions((prev) => [...prev, newReaction]);

    // Remove the reaction after animation
    setTimeout(() => {
      setEmojiReactions((prev) =>
        prev.filter((reaction) => reaction.id !== newReaction.id)
      );
    }, 5000);
  };

  useEventListener<any>("reaction", (event) => {
    if (event.type === "EMOJI") {
      showEmoji(event);
    }
  });

  console.log(jamState.jam.rooms["test"], jamState.jam.presence);

  return (
    <div className="flex h-full w-full">
      <div className="w-1/3 lg:w-1/4 bg-slate-900 h-full flex flex-col">
        <div className="p-2">room-test</div>
        <div className="flex p-2">
          <input
            type="text"
            className="bg-slate-800 flex-1"
            placeholder="Your name"
            value={username}
            onChange={(e) => setUsername(e.target.value)}
            onBlur={onSubmitUsername}
          />
        </div>
        <div className="flex p-2">
          <input
            type="text"
            className="bg-slate-800 text-xs flex-1"
            placeholder="Paste a Clip URL (Staging or Prod)"
            onChange={(e) => setClipUrlInput(e.target.value)}
            value={clipUrlInput}
            onKeyDown={(e) => {
              if (e.key == "Enter") {
                onSubmit();
              }
            }}
            onPaste={(e) => {
              // Get the pasted content from clipboard
              const pastedText = e.clipboardData.getData("text");
              // Set the input value
              setClipUrlInput(pastedText);
              // Wait for state to update before submitting
              setTimeout(() => onSubmit(pastedText), 10);
            }}
          />
        </div>
        <ul className="flex-1 overflow-y-auto my-4">
          {currentRoom.clips?.map((clip, i) => (
            <li
              key={clip.id + clip.submitterId}
              className={clsx("flex", {
                "bg-blue-900": currentRoom.playState?.clip.id === clip.id,
              })}
            >
              <button
                className="bg-blue-500 text-xs text-white px-2 py-1 rounded-md"
                onClick={() => playSong(clip)}
              >
                Play
              </button>
              <div className="flex-1 px-2 text-sm">
                <p className="text-gray-300">{clip.title}</p>
                {clip.metadata?.["tags"] && (
                  <p className="text-gray-400 text-xs">
                    {clip.metadata["tags"]}
                  </p>
                )}
                <span className="text-gray-400 text-xs">
                  {clip.submitterUsername || "Anon"}{" "}
                </span>
              </div>
              <button
                className="bg-blue-500 text-white px-2 py-1 rounded-md"
                onClick={() => {
                  deleteSong(i);
                }}
              >
                x
              </button>
            </li>
          ))}
        </ul>
        <div className="p-3 ">
          <OnlineUsers />
          <div className="flex justify-end gap-2">
            <button
              onClick={() => {
                if (currentRoom.playState?.isPlaying) {
                  pauseSong();
                }
              }}
              className="text-xs bg-blue-500 text-white px-2 py-1 rounded-md"
            >
              Pause
            </button>
            <button
              onClick={resetState}
              className="text-xs bg-blue-500 text-white px-2 py-1 rounded-md"
            >
              Reset
            </button>
          </div>
        </div>
      </div>
      <div className=" bg-black w-2/3 lg:w-3/4 overflow-y-auto p-4 space-y-8 h-full flex flex-col relative">
        {currentRoom.playState?.clip && (
          <ClipDetail clip={currentRoom.playState?.clip} />
        )}
        <EmojiBoard username={username} onSubmit={showEmoji} />
        <audio ref={audioRef} controls />
      </div>
      <div>
        {emojiReactions.map((reaction) => (
          <FloatingEmoji
            key={reaction.id}
            emoji={reaction.emoji}
            username={reaction.username}
            comment={reaction.comment}
          />
        ))}
      </div>
    </div>
  );
});

import { Jam } from "@/types";
import { createContext, useContext } from "react";
import { ClipDetail } from "./ClipDetail";
import { JamState } from "./state";

const JamStateContext = createContext<JamState | null>(null);

export const useJamState = (): JamState => {
  const context = useContext(JamStateContext);
  if (!context) {
    throw new Error("useJamState must be used within JamStateProvider");
  }
  return context;
};

const RoomWrapper = () => {
  // const jamState: JamState = new JamState(jam)

  const [jamState, setJamState] = useState<JamState | null>(null);
  useEventListener("snapshot", (jam: Jam) => {
    console.log("snapshot", jam);
    setJamState(new JamState(jam));
  });

  return jamState ? (
    <JamStateContext.Provider value={jamState}>
      <RoomBase />
    </JamStateContext.Provider>
  ) : (
    <div>Loading...</div>
  );
};

export default function Room({
  connectResponse,
}: {
  connectResponse: ConnectResponse;
}) {
  return (
    <SessionBackendProvider connectResponse={connectResponse}>
      <SocketIOProvider url={connectResponse.url}>
        <RoomWrapper />
      </SocketIOProvider>
    </SessionBackendProvider>
  );
}
