import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import DetailedMeeting from "../../api-bodies/DetailedMeeting";
import { RootState } from "../store";
import UserStatus from "../../api-bodies/UserStatus";
import axios from "../../api/axios";

interface MeetingsAndUserStatusState {
  meetings: DetailedMeeting[];
  userStatuses: Record<string, UserStatus>;
  isConnecting: boolean;
  isConnected: boolean;
}

const initialState: MeetingsAndUserStatusState = {
  meetings: [],
  userStatuses: {},
  isConnecting: false,
  isConnected: false,
};

export const meetingsAndUserStatusSlice = createSlice({
  name: "meetingsAndUserStatus",
  initialState,
  reducers: {
    startConnecting: (state) => {
      state.isConnecting = true;
    },
    connectionEstablished: (state) => {
      state.isConnecting = true;
      state.isConnected = true;
    },
    meetingCreated: (state, action) => {
      state.meetings.push(action.payload.meeting);
    },
    userStatusChanged: (state, action) => {
      state.userStatuses[action.payload.uuid] = action.payload;
    },
  },
  extraReducers(builder) {
    builder.addCase(fetchMeetings.fulfilled, (state, action) => {
      state.meetings = action.payload.meetings;
      state.userStatuses = action.payload.userStatuses;
    });
  },
});

export const fetchMeetings = createAsyncThunk(
  "meetingsAndUserStatus/fetchMeetings",
  async (uuid: string) => {
    const response = await axios.get(
      `/users/${uuid}/meetings?start=1900-01-01&end=2100-01-01`
    );
    const meetings: DetailedMeeting[] = response.data.meetings;
    const userStatuses: Record<string, UserStatus> = {};
    meetings.forEach((meeting) => {
      meeting.liveParticipantIds.forEach((uuid) => {
        userStatuses[uuid] = {
          userId: uuid,
          inMeeting: true,
          meetingId: meeting.meetingId,
        };
      });
    });
    return { userStatuses: userStatuses, meetings: meetings };
  }
);

export const selectMeetings = (state: RootState) =>
  state.meetingsAndUserStatuses.meetings;
export const selectMeeting = (state: RootState, meetingID: string | null) => {
  return meetingID !== null
    ? state.meetingsAndUserStatuses.meetings.find(
      (meeting) => meeting.meetingId === meetingID
    )
    : null;
};
export const selectUserUpcomingMeetings = (state: RootState, uuid: string) => {
  return state.meetingsAndUserStatuses.meetings.filter((meeting) =>
    meeting.registrantIds.includes(uuid)
  );
};
export const selectUserStatus = (
  state: RootState,
  uuid: string
): UserStatus => {
  const userStatus = state.meetingsAndUserStatuses.userStatuses[uuid];
  if (userStatus) {
    return userStatus;
  } else {
    return {
      userId: uuid,
      inMeeting: false,
      meetingId: null,
    };
  }
};
export const selectUserStatuses = (
  state: RootState,
  uuids: string[]
): UserStatus[] => {
  const userStatuses: UserStatus[] = [];
  uuids.forEach((uuid) => {
    const userStatus = state.meetingsAndUserStatuses.userStatuses[uuid];
    if (userStatus) {
      userStatuses.push(userStatus);
    } else {
      userStatuses.push({
        userId: uuid,
        inMeeting: false,
        meetingId: null,
      });
    }
  });
  return userStatuses;
};
export default meetingsAndUserStatusSlice.reducer;
export const socketActions = meetingsAndUserStatusSlice.actions;
