import { createFeature, createReducer, on } from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { BankAccount } from '../../models/bank-account.model';
import { PaginationMeta } from '../../models/api.model';
import { BankAccountsActions } from './bank-accounts.actions';

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

export const bankAccountsAdapter: EntityAdapter<BankAccount> = createEntityAdapter<BankAccount>();

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

export const bankAccountsFeature = createFeature({
  name: 'bankAccounts',
  reducer: createReducer(
    initialState,
    on(BankAccountsActions.loadBankAccounts, (state, action) =>
      state.loaded && !action.forceReload ? state : { ...state, loading: true, error: null }
    ),
    on(BankAccountsActions.loadBankAccountsSuccess, (state, { bankAccounts, meta }) =>
      bankAccountsAdapter.setAll(bankAccounts, { ...state, meta, loading: false, loaded: true })
    ),
    on(BankAccountsActions.loadBankAccountsFailure, (state, { error }) => ({ ...state, loading: false, error })),
    on(BankAccountsActions.createBankAccount, (state) => ({ ...state, saving: true, error: null })),
    on(BankAccountsActions.createBankAccountSuccess, (state, { bankAccount }) =>
      bankAccountsAdapter.addOne(bankAccount, { ...state, saving: false })
    ),
    on(BankAccountsActions.createBankAccountFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(BankAccountsActions.updateBankAccount, (state) => ({ ...state, saving: true, error: null })),
    on(BankAccountsActions.updateBankAccountSuccess, (state, { bankAccount }) =>
      bankAccountsAdapter.upsertOne(bankAccount, { ...state, saving: false })
    ),
    on(BankAccountsActions.updateBankAccountFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(BankAccountsActions.deleteBankAccount, (state) => ({ ...state, saving: true, error: null })),
    on(BankAccountsActions.deleteBankAccountSuccess, (state, { id }) =>
      bankAccountsAdapter.removeOne(id, { ...state, saving: false })
    ),
    on(BankAccountsActions.deleteBankAccountFailure, (state, { error }) => ({ ...state, saving: false, error })),
    on(BankAccountsActions.clearBankAccountsError, (state) => ({ ...state, error: null }))
  ),
});

const { selectAll, selectEntities, selectTotal } = bankAccountsAdapter.getSelectors(bankAccountsFeature.selectBankAccountsState);

export const selectAllBankAccounts = selectAll;
export const selectBankAccountEntities = selectEntities;
export const selectBankAccountsTotal = selectTotal;
export const selectBankAccountsMeta = bankAccountsFeature.selectMeta;
export const selectBankAccountsLoading = bankAccountsFeature.selectLoading;
export const selectBankAccountsSaving = bankAccountsFeature.selectSaving;
export const selectBankAccountsError = bankAccountsFeature.selectError;
export const selectBankAccountsLoaded = bankAccountsFeature.selectLoaded;
