import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import {
  removeAccessToken,
  initialConfig,
  loadAccessToken,
  saveAccessToken,
  loadRefreshToken,
  saveRefreshToken,
  removeRefreshToken,
} from "./utils";
import type { AuthState } from "./state";
import {
  getDelegationTokenAsync,
  updateDelegationTokenAsync,
  updateTokenAsync,
} from "./operations";

const initialState: AuthState = {
  configuration: initialConfig(),
  accessToken: loadAccessToken(),
  refreshToken: loadRefreshToken(),
  delegationAccessToken: null,
  delegationRefreshToken: null,
};

export const authSlice = createSlice({
  name: "auth",
  initialState,
  reducers: {
    setToken: (
      state,
      action: PayloadAction<{
        accessToken: string | null;
        refreshToken: string | null;
      }>
    ) => {
      const { accessToken, refreshToken } = action.payload;
      if (accessToken && refreshToken) {
        state.accessToken = accessToken;
        saveAccessToken(accessToken);

        state.refreshToken = refreshToken;
        saveRefreshToken(refreshToken);
      }
    },
    clearToken: (state) => {
      state.accessToken = null;
      state.refreshToken = null;
      removeAccessToken();
      removeRefreshToken();
    },
    clearDelegationToken: (state) => {
      state.delegationAccessToken = null;
      state.delegationRefreshToken = null;
    },
  },
  extraReducers: (builder) => {
    builder.addCase(updateTokenAsync.fulfilled, (state, action) => {
      const { accessToken } = action.payload;
      state.accessToken = accessToken;
      saveAccessToken(accessToken);
    });
    builder.addCase(getDelegationTokenAsync.fulfilled, (state, action) => {
      const { accessToken, refreshToken } = action.payload;
      state.delegationAccessToken = accessToken;
      state.delegationRefreshToken = refreshToken;
    });
    builder.addCase(updateDelegationTokenAsync.fulfilled, (state, action) => {
      const { accessToken } = action.payload;
      state.delegationAccessToken = accessToken;
    });
    builder.addCase(updateDelegationTokenAsync.rejected, (state) => {
      state.delegationAccessToken = null;
      state.delegationRefreshToken = null;
    });
  },
});

export const { setToken, clearToken, clearDelegationToken } = authSlice.actions;

export default authSlice.reducer;
