import { createFeature, createReducer, on } from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { PettyCash, PettyCashTransaction } from '../../models/petty-cash.model';
import { PaginationMeta } from '../../models/api.model';
import { PettyCashActions } from './petty-cash.actions';

export interface PettyCashState extends EntityState<PettyCash> {
  meta: PaginationMeta | null;
  transactions: PettyCashTransaction[];
  transactionsMeta: PaginationMeta | null;
  loading: boolean;
  saving: boolean;
  error: string | null;
  loaded: boolean;
}

export const pettyCashAdapter: EntityAdapter<PettyCash> = createEntityAdapter<PettyCash>();

const initialState: PettyCashState = pettyCashAdapter.getInitialState({
  meta: null, transactions: [], transactionsMeta: null, loading: false, saving: false, error: null, loaded: false,
});

export const pettyCashFeature = createFeature({
  name: 'pettyCash',
  reducer: createReducer(
    initialState,
    on(PettyCashActions.loadPettyCashList, (state, action) =>
      state.loaded && !action.forceReload ? state : { ...state, loading: true, error: null }
    ),
    on(PettyCashActions.loadPettyCashListSuccess, (state, { items, meta }) =>
      pettyCashAdapter.setAll(items, { ...state, meta, loading: false, loaded: true })
    ),
    on(PettyCashActions.loadPettyCashListFailure, (state, { error }) => ({ ...state, loading: false, error })),
    on(PettyCashActions.createPettyCash, (state) => ({ ...state, saving: true, error: null })),
    on(PettyCashActions.createPettyCashSuccess, (state, { pettyCash }) =>
      pettyCashAdapter.addOne(pettyCash, { ...state, saving: false })
    ),
    on(PettyCashActions.createPettyCashFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(PettyCashActions.updatePettyCash, (state) => ({ ...state, saving: true, error: null })),
    on(PettyCashActions.updatePettyCashSuccess, (state, { pettyCash }) =>
      pettyCashAdapter.upsertOne(pettyCash, { ...state, saving: false })
    ),
    on(PettyCashActions.updatePettyCashFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(PettyCashActions.deletePettyCash, (state) => ({ ...state, saving: true, error: null })),
    on(PettyCashActions.deletePettyCashSuccess, (state, { id }) =>
      pettyCashAdapter.removeOne(id, { ...state, saving: false })
    ),
    on(PettyCashActions.deletePettyCashFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(PettyCashActions.loadTransactions, (state) => ({ ...state, loading: true, error: null })),
    on(PettyCashActions.loadTransactionsSuccess, (state, { transactions, meta }) =>
      ({ ...state, transactions, transactionsMeta: meta, loading: false })
    ),
    on(PettyCashActions.loadTransactionsFailure, (state, { error }) => ({ ...state, loading: false, error })),
    on(PettyCashActions.createTransaction, (state) => ({ ...state, saving: true, error: null })),
    on(PettyCashActions.createTransactionSuccess, (state, { transaction }) =>
      ({ ...state, transactions: [...state.transactions, transaction], saving: false })
    ),
    on(PettyCashActions.createTransactionFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(PettyCashActions.deleteTransaction, (state) => ({ ...state, saving: true, error: null })),
    on(PettyCashActions.deleteTransactionSuccess, (state, { transactionId }) =>
      ({ ...state, transactions: state.transactions.filter(t => t.id !== transactionId), saving: false })
    ),
    on(PettyCashActions.deleteTransactionFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(PettyCashActions.clearPettyCashError, (state) => ({ ...state, error: null }))
  ),
});

const { selectAll, selectEntities, selectTotal } = pettyCashAdapter.getSelectors(pettyCashFeature.selectPettyCashState);

export const selectAllPettyCash = selectAll;
export const selectPettyCashEntities = selectEntities;
export const selectPettyCashTotal = selectTotal;
export const selectPettyCashMeta = pettyCashFeature.selectMeta;
export const selectPettyCashTransactions = pettyCashFeature.selectTransactions;
export const selectPettyCashTransactionsMeta = pettyCashFeature.selectTransactionsMeta;
export const selectPettyCashLoading = pettyCashFeature.selectLoading;
export const selectPettyCashSaving = pettyCashFeature.selectSaving;
export const selectPettyCashError = pettyCashFeature.selectError;
export const selectPettyCashLoaded = pettyCashFeature.selectLoaded;
