import { createFeature, createReducer, on } from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { PaginationMeta } from '../../../models/api.model';
import { HrDepartment } from '../../../models/hr-department.model';
import { HrDepartmentsActions } from './departments.actions';

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

export const hrDepartmentsAdapter: EntityAdapter<HrDepartment> =
  createEntityAdapter<HrDepartment>();

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

export const hrDepartmentsFeature = createFeature({
  name: 'hrDepartments',
  reducer: createReducer(
    initialState,
    // Load
    on(HrDepartmentsActions.loadHRDepartments, (state, action) =>
      state.loaded && !action.forceReload
        ? state
        : {
            ...state,
            loading: true,
            error: null,
          }
    ),
    on(HrDepartmentsActions.loadHRDepartmentsSuccess, (state, { departments, meta }) =>
      hrDepartmentsAdapter.setAll(departments, { ...state, meta, loading: false, loaded: true })
    ),
    on(HrDepartmentsActions.loadHRDepartmentsFailure, (state, { error }) => ({
      ...state,
      loading: false,
      error,
    })),
    // Create
    on(HrDepartmentsActions.createHRDepartment, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(HrDepartmentsActions.createHRDepartmentSuccess, (state, { department }) =>
      hrDepartmentsAdapter.addOne(department, { ...state, saving: false })
    ),
    on(HrDepartmentsActions.createHRDepartmentFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Update
    on(HrDepartmentsActions.updateHRDepartment, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(HrDepartmentsActions.updateHRDepartmentSuccess, (state, { department }) =>
      hrDepartmentsAdapter.upsertOne(department, { ...state, saving: false })
    ),
    on(HrDepartmentsActions.updateHRDepartmentFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Delete
    on(HrDepartmentsActions.deleteHRDepartment, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(HrDepartmentsActions.deleteHRDepartmentSuccess, (state, { id }) =>
      hrDepartmentsAdapter.removeOne(id, { ...state, saving: false })
    ),
    on(HrDepartmentsActions.deleteHRDepartmentFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Clear Error
    on(HrDepartmentsActions.clearHRDepartmentsError, (state) => ({
      ...state,
      error: null,
    }))
  ),
});

const { selectAll, selectEntities, selectTotal } = hrDepartmentsAdapter.getSelectors(
  hrDepartmentsFeature.selectHrDepartmentsState
);

export const selectAllHrDepartments = selectAll;
export const selectHrDepartmentEntities = selectEntities;
export const selectHrDepartmentsTotal = selectTotal;
export const selectHrDepartmentsMeta = hrDepartmentsFeature.selectMeta;
export const selectHrDepartmentsLoading = hrDepartmentsFeature.selectLoading;
export const selectHrDepartmentsSaving = hrDepartmentsFeature.selectSaving;
export const selectHrDepartmentsError = hrDepartmentsFeature.selectError;
export const selectHrDepartmentsLoaded = hrDepartmentsFeature.selectLoaded;
