import React, { useState, useEffect, useCallback } from "react";
import Paper from "@mui/material/Paper";
import List from "@mui/material/List";
import Button from "@mui/material/Button";
import IconButton from "@mui/material/IconButton";
import Dialog from "@mui/material/Dialog";
import DialogTitle from "@mui/material/DialogTitle";
import DialogContent from "@mui/material/DialogContent";
import DialogActions from "@mui/material/DialogActions";
import SettingsIcon from "@mui/icons-material/Settings";
import "./UserList.css";
import { MediaControl, MediaAgent, Peer } from "./MediaControl";
import Box from "@mui/material/Box";
import { Session } from "./GlobalContext";
import useWebSocket from "react-use-websocket";
import { ApiClient } from "./api-client";
import BotConfig from "./BotConfig";

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

type UserListProps = {
  socketUrl: string;
  session: Session;
  lobbyId: string;
};

const UserList: React.FC<UserListProps> = (props: UserListProps) => {
  const { socketUrl, session, lobbyId } = props;
  const [users, setUsers] = useState<User[] | null>(null);
  const [peers, setPeers] = useState<Record<string, Peer>>({});
  const [videoClass, setVideoClass] = useState<string>("Large");

  // Bot configuration state
  const [botConfigDialogOpen, setBotConfigDialogOpen] = useState(false);
  const [selectedBotForConfig, setSelectedBotForConfig] = useState<User | null>(null);
  const [leavingBots, setLeavingBots] = useState<Set<string>>(new Set());

  const apiClient = new ApiClient();

  const handleBotLeave = async (user: User) => {
    if (!user.bot_instance_id) return;

    setLeavingBots((prev) => new Set(prev).add(user.session_id));

    try {
      await apiClient.createRequestBotLeaveLobby(user.bot_instance_id);
      console.log(`Bot ${user.name} leave requested successfully`);
    } catch (error) {
      console.error("Failed to request bot leave:", error);
    } finally {
      setLeavingBots((prev) => {
        const newSet = new Set(prev);
        newSet.delete(user.session_id);
        return newSet;
      });
    }
  };

  // Bot configuration handlers
  const handleOpenBotConfig = (user: User) => {
    setSelectedBotForConfig(user);
    setBotConfigDialogOpen(true);
  };

  const handleCloseBotConfig = () => {
    setBotConfigDialogOpen(false);
    setSelectedBotForConfig(null);
  };

  const sortUsers = useCallback(
    (A: any, B: any) => {
      if (!session) {
        return 0;
      }
      /* active user first */
      if (A.name === session.name) {
        return -1;
      }
      if (B.name === session.name) {
        return +1;
      }
      /* Sort active users 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]
  );

  // Use the WebSocket hook for lobby events with automatic reconnection
  const { sendJsonMessage } = useWebSocket(socketUrl, {
    share: true,
    shouldReconnect: (closeEvent) => true, // Auto-reconnect on connection loss
    reconnectInterval: 5000,
    onMessage: (event: MessageEvent) => {
      if (!session) {
        return;
      }
      const message = JSON.parse(event.data);
      const data: any = message.data;
      switch (message.type) {
        case "lobby_state":
          type LobbyStateData = {
            participants: User[];
          };
          const lobby_state = data as LobbyStateData;
          console.log(`users - lobby_state`, lobby_state.participants);
          lobby_state.participants.forEach((user) => {
            user.local = user.session_id === session.id;
          });
          lobby_state.participants.sort(sortUsers);
          setVideoClass(lobby_state.participants.length <= 2 ? "Medium" : "Small");
          setUsers(lobby_state.participants);
          break;
        default:
          break;
      }
    },
  });

  useEffect(() => {
    if (users !== null) {
      return;
    }
    sendJsonMessage({
      type: "list_users",
    });
  }, [users, sendJsonMessage]);

  return (
    <Paper className={`UserList ${videoClass}`}>
      <MediaAgent {...{ session, socketUrl, peers, setPeers }} />
      <List className="UserSelector">
        {users?.map((user) => (
          <Box
            key={user.session_id}
            sx={{ display: "flex", flexDirection: "column", alignItems: "center" }}
            className={`UserEntry ${user.local ? "UserSelf" : ""}`}
          >
            <Box>
              <Box style={{ display: "flex-wrap", alignItems: "center", justifyContent: "space-between" }}>
                <Box style={{ display: "flex-wrap", alignItems: "center" }}>
                  <div className="Name">{user.name ? user.name : user.session_id}</div>
                  {user.protected && (
                    <div
                      style={{ marginLeft: 8, fontSize: "0.8em", color: "#a00" }}
                      title="This name is protected with a password"
                    >
                      🔒
                    </div>
                  )}
                  {user.bot_instance_id && (
                    <div style={{ marginLeft: 8, fontSize: "0.8em", color: "#00a" }} title="This is a bot">
                      🤖
                    </div>
                  )}
                </Box>
                {user.bot_instance_id && (
                  <Paper elevation={2} sx={{ display: "flex-wrap", gap: "4px", p: 1 }}>
                    {user.bot_run_id && (
                      <IconButton
                        size="small"
                        onClick={() => handleOpenBotConfig(user)}
                        style={{ width: "24px", height: "24px", fontSize: "0.7em" }}
                        title="Configure bot"
                      >
                        <SettingsIcon style={{ fontSize: "14px" }} />
                      </IconButton>
                    )}
                    <Button
                      size="small"
                      variant="outlined"
                      color="secondary"
                      onClick={() => handleBotLeave(user)}
                      disabled={leavingBots.has(user.session_id) || !user.bot_instance_id}
                      style={{ fontSize: "0.7em", minWidth: "50px", height: "24px" }}
                      title={!user.bot_instance_id ? "Bot instance ID not available" : "Remove bot from lobby"}
                    >
                      {leavingBots.has(user.session_id) ? "..." : "Leave"}
                    </Button>
                  </Paper>
                )}
              </Box>
              {user.name && !user.live && <div className="NoNetwork"></div>}
            </Box>
            {user.name && user.live && peers[user.session_id] && (user.local || user.has_media !== false) ? (
              <MediaControl
                className={videoClass}
                key={user.session_id}
                peer={peers[user.session_id]}
                isSelf={user.local}
              />
            ) : user.name && user.live && user.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>

      {/* Bot Configuration Dialog */}
      <Dialog open={botConfigDialogOpen} onClose={handleCloseBotConfig} maxWidth="md" fullWidth>
        <DialogTitle>Configure Bot</DialogTitle>
        <DialogContent>
          {selectedBotForConfig && (
            <BotConfig
              botName={selectedBotForConfig.name?.replace(/-bot$/, "") || "unknown"}
              lobbyId={lobbyId}
              onConfigUpdate={(config) => {
                console.log("Bot configuration updated:", config);
                // Configuration updates are handled via WebSocket, so we don't need to do anything special here
              }}
            />
          )}
        </DialogContent>
        <DialogActions>
          <Button onClick={handleCloseBotConfig}>Close</Button>
        </DialogActions>
      </Dialog>
    </Paper>
  );
};

export { UserList };
