import { createFeature, createReducer, on } from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { CheckReceived } from '../../models/check-received.model';
import { PaginationMeta } from '../../models/api.model';
import { ChecksReceivedActions } from './checks-received.actions';

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

export const checksReceivedAdapter: EntityAdapter<CheckReceived> = createEntityAdapter<CheckReceived>();

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

export const checksReceivedFeature = createFeature({
  name: 'checksReceived',
  reducer: createReducer(
    initialState,
    on(ChecksReceivedActions.loadChecksReceived, (state, action) =>
      state.loaded && !action.forceReload ? state : { ...state, loading: true, error: null }
    ),
    on(ChecksReceivedActions.loadChecksReceivedSuccess, (state, { checks, meta }) =>
      checksReceivedAdapter.setAll(checks, { ...state, meta, loading: false, loaded: true })
    ),
    on(ChecksReceivedActions.loadChecksReceivedFailure, (state, { error }) => ({ ...state, loading: false, error })),
    on(ChecksReceivedActions.createCheckReceived, (state) => ({ ...state, saving: true, error: null })),
    on(ChecksReceivedActions.createCheckReceivedSuccess, (state, { check }) =>
      checksReceivedAdapter.addOne(check, { ...state, saving: false })
    ),
    on(ChecksReceivedActions.createCheckReceivedFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(ChecksReceivedActions.updateCheckReceived, (state) => ({ ...state, saving: true, error: null })),
    on(ChecksReceivedActions.updateCheckReceivedSuccess, (state, { check }) =>
      checksReceivedAdapter.upsertOne(check, { ...state, saving: false })
    ),
    on(ChecksReceivedActions.updateCheckReceivedFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(ChecksReceivedActions.deleteCheckReceived, (state) => ({ ...state, saving: true, error: null })),
    on(ChecksReceivedActions.deleteCheckReceivedSuccess, (state, { id }) =>
      checksReceivedAdapter.removeOne(id, { ...state, saving: false })
    ),
    on(ChecksReceivedActions.deleteCheckReceivedFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(ChecksReceivedActions.depositCheckReceived, (state) => ({ ...state, saving: true, error: null })),
    on(ChecksReceivedActions.depositCheckReceivedSuccess, (state, { check }) =>
      checksReceivedAdapter.upsertOne(check, { ...state, saving: false })
    ),
    on(ChecksReceivedActions.depositCheckReceivedFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(ChecksReceivedActions.collectCheckReceived, (state) => ({ ...state, saving: true, error: null })),
    on(ChecksReceivedActions.collectCheckReceivedSuccess, (state, { check }) =>
      checksReceivedAdapter.upsertOne(check, { ...state, saving: false })
    ),
    on(ChecksReceivedActions.collectCheckReceivedFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(ChecksReceivedActions.clearChecksReceivedError, (state) => ({ ...state, error: null }))
  ),
});

const { selectAll, selectEntities, selectTotal } = checksReceivedAdapter.getSelectors(checksReceivedFeature.selectChecksReceivedState);

export const selectAllChecksReceived = selectAll;
export const selectCheckReceivedEntities = selectEntities;
export const selectChecksReceivedTotal = selectTotal;
export const selectChecksReceivedMeta = checksReceivedFeature.selectMeta;
export const selectChecksReceivedLoading = checksReceivedFeature.selectLoading;
export const selectChecksReceivedSaving = checksReceivedFeature.selectSaving;
export const selectChecksReceivedError = checksReceivedFeature.selectError;
export const selectChecksReceivedLoaded = checksReceivedFeature.selectLoaded;
