import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import roomService from "../services/roomService";
import notificationService from "../services/notificationService";

const initialState = {
  status: "idle",
  rooms: [],
  activeRoom: null,
  error: null,
  connection: null,
  messages: [],
  connections: [],
  notifications: [],
  typings: [],
};

export const fetchChatRoomsAsync = createAsyncThunk(
  "chat/fetchChatRoomsAsync",
  async (payload, thunkAPI) => {
    try {
      return await roomService.getRooms(payload);
    } catch (error) {
      return thunkAPI.rejectWithValue({ error });
    }
  }
);

export const fetchSupportRoomsAsync = createAsyncThunk(
  "chat/fetchSupportRooms",
  async (payload, thunkAPI) => {
    try {
      return await roomService.getSupportRooms(payload);
    } catch (error) {
      return thunkAPI.rejectWithValue({ error });
    }
  }
);

export const createChatRoomAsync = createAsyncThunk(
  "chat/createChatRoomAsync",
  async (payload, thunkAPI) => {
    try {
      return await roomService.createRoom(payload);
    } catch (error) {
      return thunkAPI.rejectWithValue({ error });
    }
  }
);

export const loadNotifications = createAsyncThunk(
  "chat/loadNotifications",
  async (payload, thunkAPI) => {
    try {
      return await notificationService.loadNotifications(payload);
    } catch (error) {
      return thunkAPI.rejectWithValue({ error });
    }
  }
);

export const readNotificationsAsync = createAsyncThunk(
  "chat/deleteNotificationsAsync",
  async (payload, thunkAPI) => {
    try {
      return await notificationService.readNotifications(payload);
    } catch (error) {
      return thunkAPI.rejectWithValue({ error });
    }
  }
);

const chatSlice = createSlice({
  name: "chat",
  initialState,
  reducers: {
    setAllChats: (state, action) => {
      state.rooms = action.payload;
    },
    setRoom: (state, action) => {
      state.activeRoom = action.payload;
    },
    deleteActiveRoom: (state, action) => {
      state.activeRoom = null;
    },
    // Set hub connection
    setConnection: (state, action) => {
      state.connection = action.payload;
    },
    // New message sent from user
    newMessage: (state, action) => {
      if (action.payload.changedRoom) {
        state.messages = [];
      } else {
        state.messages = [...state.messages, action.payload];
      }
    },
    saveContextId: (state, action) => {
      // Check is empty array
      // If array is not empty, check is connection for specific room and specific user already added
      if (state.connections.length > 0) {
        if (
          !state.connections.some(
            (e) => e.connId === action.payload && e.roomId === state.activeRoom
          )
        ) {
          state.connections.push({
            connId: action.payload.connId,
            roomId: state.activeRoom.id,
            userId: action.payload.userId,
          });
        }
      } else {
        // If array is empty, add connection
        state.connections.push({
          connId: action.payload.connId,
          roomId: state.activeRoom.id,
          userId: action.payload.userId,
        });
      }
    },
    // Set messages fetched from backend for specific room
    setMessages: (state, action) => {
      state.messages = action.payload;
    },
    addNotification: (state, action) => {
      if (state.notifications.length !== 0) {
        const room = state.notifications.find(
          (notification) => notification.roomId === action.payload
        );

        if (room) {
          room.notificationCount++;
        } else {
          state.notifications.push({
            roomId: action.payload,
            notificationCount: 1,
          });
        }
      } else {
        state.notifications.push({
          roomId: action.payload,
          notificationCount: 1,
        });
      }
    },
    readNotifications: (state, action) => {
      state.notifications = state.notifications.filter(
        (notification) => notification.roomId !== action.payload
      );
    },
    leaveRoom: (state, action) => {
      state.activeRoom = null;

      const room = state.rooms.find(
        (room) => room.id === action.payload.roomId
      );

      room.customers = room.customers.filter(
        (customer) => customer.customerId !== action.payload.customerId
      );
    },
    addTyping: (state, action) => {
      if (
        !state.typings.some(
          (n) =>
            n.message === action.payload.message &&
            n.roomId === action.payload.roomId
        )
      )
        state.typings = [...state.typings, action.payload];
      else console.log("ima vec");
    },
    removeTyping: (state, action) => {
      if (state.typings.length >= 1) {
        let f = state.typings[0];
        state.typings = state.typings.filter((n) => n.message !== f.message);
      }
    },
  },
  extraReducers: (builder) => {
    // Fetch chat rooms
    builder.addCase(fetchChatRoomsAsync.pending, (state) => {
      state.status = "pendingFetchRooms";
      state.error = null;
    });
    builder.addCase(fetchChatRoomsAsync.fulfilled, (state, action) => {
      state.rooms = action.payload;
      state.status = "idle";
      state.error = null;
    });
    builder.addCase(fetchChatRoomsAsync.rejected, (state, action) => {
      state.status = "idle";
      state.error = "Fetch error" + action.payload;
    });

    // fetch rooms that support created
    builder.addCase(fetchSupportRoomsAsync.pending, (state) => {
      state.status = "pendingFetchRooms";
      state.error = null;
    });
    builder.addCase(fetchSupportRoomsAsync.fulfilled, (state, action) => {
      state.rooms = action.payload;
      state.status = "idle";
      state.error = null;
    });
    builder.addCase(fetchSupportRoomsAsync.rejected, (state, action) => {
      state.status = "idle";
      state.error = "Fetch error" + action.payload;
    });

    // Add chat room
    builder.addCase(createChatRoomAsync.pending, (state) => {
      state.status = "pendingAddRoom";
      state.error = null;
    });
    builder.addCase(createChatRoomAsync.fulfilled, (state, action) => {
      state.status = "idle";
      state.rooms = [...state.rooms, action.payload];
      state.error = null;
    });
    builder.addCase(createChatRoomAsync.rejected, (state, action) => {
      state.status = "idle";
      state.error = action.payload;
    });

    builder.addCase(loadNotifications.pending, (state) => {
      state.status = "pendingLoadingNotification";
      state.error = null;
    });
    builder.addCase(loadNotifications.fulfilled, (state, action) => {
      state.status = "idle";
      if (action.payload.length === 0) {
        state.notifications = [];
      } else {
        state.notifications = action.payload.map((n) => {
          return { roomId: n.roomId, notificationCount: n.count };
        });
      }
      state.error = null;
    });
    builder.addCase(loadNotifications.rejected, (state, action) => {
      state.status = "idle";
      state.error = action.payload;
    });

    // Read notifications
    builder.addCase(readNotificationsAsync.pending, (state) => {
      state.status = "pendingReadingNotifications";
      state.error = null;
    });
    builder.addCase(readNotificationsAsync.fulfilled, (state) => {
      state.status = "idle";
      state.error = null;
    });
    builder.addCase(readNotificationsAsync.rejected, (state, action) => {
      state.status = "idle";
      state.error = action.payload;
    });
  },
});

export const chatActions = chatSlice.actions;
export const chatReducers = chatSlice.reducer;
