import { combineReducers } from 'redux';
import { getFailureActionType, getRequestActionType, getSuccessActionType } from '../utils';
import { FETCH_NEW_TOKEN, FETCH_TOKEN, LOGOUT } from '../constants/auth';
import {
  ACCESS_TOKEN_KEY,
  ANONYMOUS,
  AUTHENTICATED,
  INIT,
  LOADING,
  REFRESH_TOKEN_KEY,
  STUDENT
} from '../constants';
import { FETCH_USER } from '../constants/user';
import { CREATE_STUDENT, FETCH_STUDENT } from '../constants/student';

function status(state = INIT, action) {
  switch (action.type) {
    case getRequestActionType(FETCH_TOKEN):
      return LOADING;
    case getSuccessActionType(FETCH_TOKEN):
    case getSuccessActionType(FETCH_USER):
      return state === STUDENT ? STUDENT : AUTHENTICATED;
    case getSuccessActionType(FETCH_STUDENT):
    case getSuccessActionType(CREATE_STUDENT):
      return STUDENT;
    case LOGOUT:
    case getFailureActionType(FETCH_TOKEN):
    case getFailureActionType(FETCH_USER):
      return ANONYMOUS;
    case getFailureActionType(FETCH_STUDENT):
      return action.payload.data?.code === 'student_not_found' ? AUTHENTICATED : ANONYMOUS;
    default:
      return state;
  }
}

function accessToken(state = null, action) {
  switch (action.type) {
    case getSuccessActionType(FETCH_TOKEN):
    case getSuccessActionType(FETCH_NEW_TOKEN):
      localStorage.setItem(ACCESS_TOKEN_KEY, action.payload.access);
      return action.payload.access;

    case getFailureActionType(FETCH_NEW_TOKEN):
    case LOGOUT:
      localStorage.removeItem(ACCESS_TOKEN_KEY);
      return null;

    default:
      return state;
  }
}

function refreshToken(state = null, action) {
  switch (action.type) {
    case getSuccessActionType(FETCH_TOKEN):
      localStorage.setItem(REFRESH_TOKEN_KEY, action.payload.refresh);
      return action.payload.refresh;

    case getFailureActionType(FETCH_NEW_TOKEN):
    case LOGOUT:
      localStorage.removeItem(REFRESH_TOKEN_KEY);
      return null;

    default:
      return state;
  }
}

export default combineReducers({
  status,
  // error: getErrorReducer([FETCH_TOKEN]),
  tokens: combineReducers({
    access: accessToken,
    refresh: refreshToken
  })
});
