import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { getSessions, getFriendsSessions, getPublicSessions, getInactiveSessions, getPersonById } from '../../helpers/rest'

const initialState = {
  sessions: [],
  people: [],
  status: 'idel',
  error: null,
}

export const fetchSessions = createAsyncThunk(
  "session/fetchSessions",
  async (options, thunkAPI) => {
    const response = await getSessions();
    return response.json();
  }
)

export const fetchFriendsSessions = createAsyncThunk(
  "session/fetchFriendsSessions",
  async (options, thunkAPI) => {
    const response = await getFriendsSessions(options);
    return response.json();
  }
)

export const fetchPublicSessions = createAsyncThunk(
  "session/fetchPublicSessions",
  async (options, thunkAPI) => {
    const response = await getPublicSessions(options);
    return response.json();
  }
)

export const fetchInactiveSessions = createAsyncThunk(
  "session/fetchInactiveSessions",
  async (options, thunkAPI) => {
    const response = await getInactiveSessions(options);
    return response.json();
  }
)

export const fetchPerson = createAsyncThunk(
  'session/fetchPerson',
  async (options, thunkAPI) => {
    const { userId } = options
    const response = await getPersonById(userId)
    return response.json()
  }
  , {
    condition: (options, { getState, extra }) => {
      const { session } = getState()
      const { userId } = options
      const person = session.people.find(person => person.id === userId)
      if (person && person.website) {
        //only proceed if full data set for user has not been fetched. person.website is not included in the initial data fetching (i.e: in friends listing ).
        return false;
      }
    }
  }
)

export const SessionSlice = createSlice({
  name: "session",
  initialState,
  reducers: {
    addSession: (state) => { },
    updateSession: (state) => { },
    deleteSession: (state) => { },
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchSessions.pending, (state, action) => {
        state.status = "loading";
      })
      .addCase(fetchSessions.fulfilled, (state, action) => {
        // add unique sessions to the array
        const records = new Set([...state.sessions, ...action.payload]);
        const unique = [];
        records.map(x => unique.filter(p => p.id === x.id).length > 0 ? null : unique.push(x))
        state.sessions = unique;
        state.error = null;
        state.status = "succeeded";
      })
      .addCase(fetchSessions.rejected, (state, action) => {
        state.status = 'failed'
        state.error = action.error.message
      })
      .addCase(fetchFriendsSessions.pending, (state, action) => {
        state.status = "loading";
      })
      .addCase(fetchFriendsSessions.fulfilled, (state, action) => {
        // add unique sessions to the array
        const records = new Set([...state.sessions, ...action.payload.sessions]);
        const unique = [];
        records.map(x => unique.filter(p => p.id === x.id).length > 0 ? null : unique.push(x))
        state.sessions = unique;
        state.error = null;
        state.status = "succeeded";
      })
      .addCase(fetchPublicSessions.pending, (state, action) => {
        state.status = "loading";
      })
      .addCase(fetchPublicSessions.fulfilled, (state, action) => {
        // add unique sessions to the array
        const records = new Set([...state.sessions, ...action.payload.sessions]);
        const unique = [];
        records.map(x => unique.filter(p => p.id === x.id).length > 0 ? null : unique.push(x))
        state.sessions = unique;
        state.error = null;
        state.status = "succeeded";
      })
      .addCase(fetchInactiveSessions.pending, (state, action) => {
        state.status = "loading";
      })
      .addCase(fetchInactiveSessions.fulfilled, (state, action) => {
        // add unique sessions to the array
        const records = new Set([...state.sessions, ...action.payload.sessions]);
        const unique = [];
        records.map(x => unique.filter(p => p.id === x.id).length > 0 ? null : unique.push(x))
        state.sessions = unique;
        state.error = null;
        state.status = "succeeded";
      })
      .addCase(fetchPerson.fulfilled, (state, action) => {
        const person = state.people.find(person => person.id === action.payload.id)
        if (person) {
          const updated = {
            ...person,
            ...action.payload
          }
          const objIndex = state.people.findIndex((p => p.id === updated.id));
          state.people[objIndex] = updated
        } else {
          state.people.push(action.payload)
        }
      })
  }
})

export default SessionSlice.reducer;