import { createFeature, createReducer, on } from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { PaginationMeta } from '../../../models/api.model';
import { HrPayroll } from '../../../models/hr-payroll.model';
import { HrPayrollActions } from './payroll.actions';

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

export const hrPayrollAdapter: EntityAdapter<HrPayroll> = createEntityAdapter<HrPayroll>();

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

export const hrPayrollFeature = createFeature({
  name: 'hrPayroll',
  reducer: createReducer(
    initialState,
    // Load
    on(HrPayrollActions.loadHRPayroll, (state, action) =>
      state.loaded && !action.forceReload
        ? state
        : {
            ...state,
            loading: true,
            error: null,
          }
    ),
    on(HrPayrollActions.loadHRPayrollSuccess, (state, { payrolls, meta }) =>
      hrPayrollAdapter.setAll(payrolls, { ...state, meta, loading: false, loaded: true })
    ),
    on(HrPayrollActions.loadHRPayrollFailure, (state, { error }) => ({
      ...state,
      loading: false,
      error,
    })),
    // Create
    on(HrPayrollActions.createHRPayroll, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(HrPayrollActions.createHRPayrollSuccess, (state, { payroll }) =>
      hrPayrollAdapter.addOne(payroll, { ...state, saving: false })
    ),
    on(HrPayrollActions.createHRPayrollFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Update
    on(HrPayrollActions.updateHRPayroll, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(HrPayrollActions.updateHRPayrollSuccess, (state, { payroll }) =>
      hrPayrollAdapter.upsertOne(payroll, { ...state, saving: false })
    ),
    on(HrPayrollActions.updateHRPayrollFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Delete
    on(HrPayrollActions.deleteHRPayroll, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(HrPayrollActions.deleteHRPayrollSuccess, (state, { id }) =>
      hrPayrollAdapter.removeOne(id, { ...state, saving: false })
    ),
    on(HrPayrollActions.deleteHRPayrollFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Calculate
    on(HrPayrollActions.calculateHRPayroll, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(HrPayrollActions.calculateHRPayrollSuccess, (state, { payroll }) =>
      hrPayrollAdapter.upsertOne(payroll, { ...state, saving: false })
    ),
    on(HrPayrollActions.calculateHRPayrollFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Approve
    on(HrPayrollActions.approveHRPayroll, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(HrPayrollActions.approveHRPayrollSuccess, (state, { payroll }) =>
      hrPayrollAdapter.upsertOne(payroll, { ...state, saving: false })
    ),
    on(HrPayrollActions.approveHRPayrollFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Post
    on(HrPayrollActions.postHRPayroll, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(HrPayrollActions.postHRPayrollSuccess, (state, { payroll }) =>
      hrPayrollAdapter.upsertOne(payroll, { ...state, saving: false })
    ),
    on(HrPayrollActions.postHRPayrollFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Clear Error
    on(HrPayrollActions.clearHRPayrollError, (state) => ({
      ...state,
      error: null,
    }))
  ),
});

const { selectAll, selectEntities, selectTotal } = hrPayrollAdapter.getSelectors(
  hrPayrollFeature.selectHrPayrollState
);

export const selectAllHrPayroll = selectAll;
export const selectHrPayrollEntities = selectEntities;
export const selectHrPayrollTotal = selectTotal;
export const selectHrPayrollMeta = hrPayrollFeature.selectMeta;
export const selectHrPayrollLoading = hrPayrollFeature.selectLoading;
export const selectHrPayrollSaving = hrPayrollFeature.selectSaving;
export const selectHrPayrollError = hrPayrollFeature.selectError;
export const selectHrPayrollLoaded = hrPayrollFeature.selectLoaded;
