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

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

export const checksIssuedAdapter: EntityAdapter<CheckIssued> = createEntityAdapter<CheckIssued>();

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

export const checksIssuedFeature = createFeature({
  name: 'checksIssued',
  reducer: createReducer(
    initialState,
    on(ChecksIssuedActions.loadChecksIssued, (state, action) =>
      state.loaded && !action.forceReload ? state : { ...state, loading: true, error: null }
    ),
    on(ChecksIssuedActions.loadChecksIssuedSuccess, (state, { checks, meta }) =>
      checksIssuedAdapter.setAll(checks, { ...state, meta, loading: false, loaded: true })
    ),
    on(ChecksIssuedActions.loadChecksIssuedFailure, (state, { error }) => ({ ...state, loading: false, error })),
    on(ChecksIssuedActions.createCheckIssued, (state) => ({ ...state, saving: true, error: null })),
    on(ChecksIssuedActions.createCheckIssuedSuccess, (state, { check }) =>
      checksIssuedAdapter.addOne(check, { ...state, saving: false })
    ),
    on(ChecksIssuedActions.createCheckIssuedFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(ChecksIssuedActions.updateCheckIssued, (state) => ({ ...state, saving: true, error: null })),
    on(ChecksIssuedActions.updateCheckIssuedSuccess, (state, { check }) =>
      checksIssuedAdapter.upsertOne(check, { ...state, saving: false })
    ),
    on(ChecksIssuedActions.updateCheckIssuedFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(ChecksIssuedActions.deleteCheckIssued, (state) => ({ ...state, saving: true, error: null })),
    on(ChecksIssuedActions.deleteCheckIssuedSuccess, (state, { id }) =>
      checksIssuedAdapter.removeOne(id, { ...state, saving: false })
    ),
    on(ChecksIssuedActions.deleteCheckIssuedFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(ChecksIssuedActions.deliverCheckIssued, (state) => ({ ...state, saving: true, error: null })),
    on(ChecksIssuedActions.deliverCheckIssuedSuccess, (state, { check }) =>
      checksIssuedAdapter.upsertOne(check, { ...state, saving: false })
    ),
    on(ChecksIssuedActions.deliverCheckIssuedFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(ChecksIssuedActions.cashCheckIssued, (state) => ({ ...state, saving: true, error: null })),
    on(ChecksIssuedActions.cashCheckIssuedSuccess, (state, { check }) =>
      checksIssuedAdapter.upsertOne(check, { ...state, saving: false })
    ),
    on(ChecksIssuedActions.cashCheckIssuedFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(ChecksIssuedActions.cancelCheckIssued, (state) => ({ ...state, saving: true, error: null })),
    on(ChecksIssuedActions.cancelCheckIssuedSuccess, (state, { check }) =>
      checksIssuedAdapter.upsertOne(check, { ...state, saving: false })
    ),
    on(ChecksIssuedActions.cancelCheckIssuedFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(ChecksIssuedActions.clearChecksIssuedError, (state) => ({ ...state, error: null }))
  ),
});

const { selectAll, selectEntities, selectTotal } = checksIssuedAdapter.getSelectors(checksIssuedFeature.selectChecksIssuedState);

export const selectAllChecksIssued = selectAll;
export const selectCheckIssuedEntities = selectEntities;
export const selectChecksIssuedTotal = selectTotal;
export const selectChecksIssuedMeta = checksIssuedFeature.selectMeta;
export const selectChecksIssuedLoading = checksIssuedFeature.selectLoading;
export const selectChecksIssuedSaving = checksIssuedFeature.selectSaving;
export const selectChecksIssuedError = checksIssuedFeature.selectError;
export const selectChecksIssuedLoaded = checksIssuedFeature.selectLoaded;
