import { createFeature, createReducer, on } from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { PaginationMeta } from '../../../models/api.model';
import { HrLoan } from '../../../models/hr-loan.model';
import { HrLoansActions } from './loans.actions';

export interface HrLoansState extends EntityState<HrLoan> {
  meta: PaginationMeta | null;
  loading: boolean;
  saving: boolean;
  error: string | null;
  loaded: boolean;
}

export const hrLoansAdapter: EntityAdapter<HrLoan> = createEntityAdapter<HrLoan>();

const initialState: HrLoansState = hrLoansAdapter.getInitialState({
  meta: null,
  loading: false,
  saving: false,
  error: null,
  loaded: false,
});

export const hrLoansFeature = createFeature({
  name: 'hrLoans',
  reducer: createReducer(
    initialState,
    // Load
    on(HrLoansActions.loadHRLoans, (state, action) =>
      state.loaded && !action.forceReload
        ? state
        : {
            ...state,
            loading: true,
            error: null,
          }
    ),
    on(HrLoansActions.loadHRLoansSuccess, (state, { loans, meta }) =>
      hrLoansAdapter.setAll(loans, { ...state, meta, loading: false, loaded: true })
    ),
    on(HrLoansActions.loadHRLoansFailure, (state, { error }) => ({
      ...state,
      loading: false,
      error,
    })),
    // Create
    on(HrLoansActions.createHRLoan, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(HrLoansActions.createHRLoanSuccess, (state, { loan }) =>
      hrLoansAdapter.addOne(loan, { ...state, saving: false })
    ),
    on(HrLoansActions.createHRLoanFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Update
    on(HrLoansActions.updateHRLoan, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(HrLoansActions.updateHRLoanSuccess, (state, { loan }) =>
      hrLoansAdapter.upsertOne(loan, { ...state, saving: false })
    ),
    on(HrLoansActions.updateHRLoanFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Delete
    on(HrLoansActions.deleteHRLoan, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(HrLoansActions.deleteHRLoanSuccess, (state, { id }) =>
      hrLoansAdapter.removeOne(id, { ...state, saving: false })
    ),
    on(HrLoansActions.deleteHRLoanFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Approve
    on(HrLoansActions.approveHRLoan, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(HrLoansActions.approveHRLoanSuccess, (state, { loan }) =>
      hrLoansAdapter.upsertOne(loan, { ...state, saving: false })
    ),
    on(HrLoansActions.approveHRLoanFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Reject
    on(HrLoansActions.rejectHRLoan, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(HrLoansActions.rejectHRLoanSuccess, (state, { loan }) =>
      hrLoansAdapter.upsertOne(loan, { ...state, saving: false })
    ),
    on(HrLoansActions.rejectHRLoanFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Clear Error
    on(HrLoansActions.clearHRLoansError, (state) => ({
      ...state,
      error: null,
    }))
  ),
});

const { selectAll, selectEntities, selectTotal } = hrLoansAdapter.getSelectors(
  hrLoansFeature.selectHrLoansState
);

export const selectAllHrLoans = selectAll;
export const selectHrLoanEntities = selectEntities;
export const selectHrLoansTotal = selectTotal;
export const selectHrLoansMeta = hrLoansFeature.selectMeta;
export const selectHrLoansLoading = hrLoansFeature.selectLoading;
export const selectHrLoansSaving = hrLoansFeature.selectSaving;
export const selectHrLoansError = hrLoansFeature.selectError;
export const selectHrLoansLoaded = hrLoansFeature.selectLoaded;
