import React, { useState, useEffect, useCallback, useContext } from "react";
import Paper from "@mui/material/Paper";
import List from "@mui/material/List";
import "./PlayerList.css";
import { MediaControl, MediaAgent, Peer } from "./MediaControl";
import { PlayerColor } from "./PlayerColor";
import Box from "@mui/material/Box";
import { GlobalContext } from "./GlobalContext";

type Player = {
  name: string;
  session_id: string;
  live: boolean;
  local: boolean /* Client side variable */;
  protected?: boolean;
  has_media?: boolean; // Whether this Player provides audio/video streams
  color?: string;
  bot_run_id?: string;
  bot_provider_id?: string;
  bot_instance_id?: string; // For bot instances
  muted?: boolean;
  video_on?: boolean;
};

const PlayerList: React.FC = () => {
  const { session, socketUrl, lastJsonMessage, sendJsonMessage } = useContext(GlobalContext);
  const [players, setPlayers] = useState<Player[] | null>(null);
  const [peers, setPeers] = useState<Record<string, Peer>>({});
  useEffect(() => {
    console.log("player-list - Mounted - requesting fields");
    if (sendJsonMessage) {
      sendJsonMessage({
        type: "get",
        fields: ["participants"],
      });
    }
  }, [sendJsonMessage]);

  const sortPlayers = useCallback(
    (A: any, B: any) => {
      if (!session) {
        return 0;
      }
      /* active Player first */
      if (A.name === session.name) {
        return -1;
      }
      if (B.name === session.name) {
        return +1;
      }
      /* Sort active Players first */
      if (A.name && !B.name) {
        return -1;
      }
      if (B.name && !A.name) {
        return +1;
      }
      /* Otherwise, sort by color */
      if (A.color && B.color) {
        return A.color.localeCompare(B.color);
      }
      return 0;
    },
    [session]
  );

  useEffect(() => {
    if (!players) {
      return;
    }
    players.forEach((player) => {
      console.log("rabbit - player:", {
        name: player.name,
        live: player.live,
        in_peers: peers[player.session_id],
        local_or_media: player.local || player.has_media !== false,
      });
    });
  }, [players]);

  // Use the WebSocket hook for room events with automatic reconnection
  useEffect(() => {
    if (!lastJsonMessage) {
      return;
    }
    const data: any = lastJsonMessage;
    switch (data.type) {
      case "game-update": {
        console.log(`player-list - game-update:`, data.update);

        // Handle participants list
        if ("participants" in data.update && data.update.participants) {
          const participantsList: Player[] = data.update.participants;
          console.log(`player-list - participants:`, participantsList);

          participantsList.forEach((player) => {
            player.local = player.session_id === session?.id;
          });
          participantsList.sort(sortPlayers);
          console.log(`player-list - sorted participants:`, participantsList);
          setPlayers(participantsList);

          // Initialize peers with remote mute/video state
          setPeers((prevPeers) => {
            const updated: Record<string, Peer> = { ...prevPeers };
            participantsList.forEach((player) => {
              // Only update remote peers, never overwrite local peer object
              if (!player.local && updated[player.session_id]) {
                updated[player.session_id] = {
                  ...updated[player.session_id],
                  muted: player.muted ?? false,
                  video_on: player.video_on ?? true,
                };
              }
            });
            return updated;
          });
        }
        break;
      }
      case "peer_state_update": {
        // Update peer state in peers, but do not override local mute
        setPeers((prevPeers) => {
          const updated = { ...prevPeers };
          const peerId = data.data?.peer_id || data.peer_id;
          if (peerId && updated[peerId]) {
            updated[peerId] = {
              ...updated[peerId],
              muted: data.data?.muted ?? data.muted,
              video_on: data.data?.video_on ?? data.video_on,
            };
          }
          return updated;
        });
        break;
      }
      default:
        // console.log(`player-list - ignoring message: ${data.type}`);
        break;
    }
  }, [lastJsonMessage, session, sortPlayers, setPeers, setPlayers]);

  useEffect(() => {
    if (players !== null || !sendJsonMessage) {
      return;
    }
    // Request participants list
    sendJsonMessage({
      type: "get",
      fields: ["participants"],
    });
  }, [players, sendJsonMessage]);

  return (
    <Box sx={{ position: "relative", width: "100%" }}>
      <Paper
        className={`player-list Medium`}
        sx={{
          maxWidth: { xs: "100%", sm: 500 },
          p: { xs: 1, sm: 2 },
          m: { xs: 0, sm: 2 },
        }}
      >
        <MediaAgent {...{ session, peers, setPeers }} />
        <List className="PlayerSelector">
          {players?.map((player) => {
            const peerObj = peers[player.session_id] || peers[player.name];
            return (
              <Box
                key={player.session_id}
                sx={{ display: "flex", flexDirection: "column", alignItems: "center" }}
                className={`PlayerEntry ${player.local ? "PlayerSelf" : ""}`}
              >
                <Box>
                  <Box style={{ display: "flex-wrap", alignItems: "center", justifyContent: "space-between" }}>
                    <Box style={{ display: "flex-wrap", alignItems: "center" }}>
                      <div className="Name">{player.name ? player.name : player.session_id}</div>
                      {player.protected && (
                        <div
                          style={{ marginLeft: 8, fontSize: "0.8em", color: "#a00" }}
                          title="This name is protected with a password"
                        >
                          🔒
                        </div>
                      )}
                      {player.bot_instance_id && (
                        <div style={{ marginLeft: 8, fontSize: "0.8em", color: "#00a" }} title="This is a bot">
                          🤖
                        </div>
                      )}
                    </Box>
                  </Box>
                  {player.name && !player.live && <div className="NoNetwork"></div>}
                </Box>
                {player.name && player.live && peerObj && (player.local || player.has_media !== false) ? (
                  <>
                    <MediaControl
                      className="Medium"
                      key={player.session_id}
                      peer={peerObj}
                      isSelf={player.local}
                      sendJsonMessage={player.local ? sendJsonMessage : undefined}
                      remoteAudioMuted={peerObj?.muted}
                      remoteVideoOff={peerObj?.video_on === false}
                    />

                    {/* If this is the local player and they haven't picked a color, show a picker */}
                    {player.local && player.color === "unassigned" && (
                      <div style={{ marginTop: 8, width: "100%" }}>
                        <div style={{ marginBottom: 6, fontSize: "0.9em" }}>Pick your color:</div>
                        <div style={{ display: "flex", gap: 8 }}>
                          {["orange", "red", "white", "blue"].map((c) => (
                            <Box
                              key={c}
                              sx={{
                                display: "flex",
                                alignItems: "center",
                                gap: 8,
                                padding: "6px 8px",
                                borderRadius: 6,
                                border: "1px solid #ccc",
                                background: "#fff",
                                cursor: sendJsonMessage ? "pointer" : "not-allowed",
                              }}
                              onClick={() => {
                                if (!sendJsonMessage) return;
                                sendJsonMessage({ type: "set", field: "color", value: c[0].toUpperCase() });
                              }}
                            >
                              <PlayerColor color={c} />
                            </Box>
                          ))}
                        </div>
                      </div>
                    )}
                  </>
                ) : player.name && player.live && player.has_media === false ? (
                  <div
                    className="Video fade-in"
                    style={{
                      background: "#333",
                      color: "#fff",
                      display: "flex",
                      alignItems: "center",
                      justifyContent: "center",
                      width: "100%",
                      height: "100%",
                      fontSize: "14px",
                    }}
                  >
                    💬 Chat Only
                  </div>
                ) : (
                  <video className="Video"></video>
                )}
              </Box>
            );
          })}
        </List>
      </Paper>
    </Box>
  );
};

export { PlayerList };
