import { createFeature, createReducer, on } from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { SalesReturn } from '../../../models/sales-return.model';
import { PaginationMeta } from '../../../models/api.model';
import { SalesReturnsActions } from './returns.actions';

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

export const salesReturnsAdapter: EntityAdapter<SalesReturn> = createEntityAdapter<SalesReturn>();

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

export const salesReturnsFeature = createFeature({
  name: 'salesReturns',
  reducer: createReducer(
    initialState,
    on(SalesReturnsActions.loadReturns, (state, action) =>
      state.loaded && !action.force ? state : { ...state, loading: true, error: null }
    ),
    on(SalesReturnsActions.loadReturnsSuccess, (state, { returns, meta }) =>
      salesReturnsAdapter.setAll(returns, { ...state, meta, loading: false, loaded: true })
    ),
    on(SalesReturnsActions.loadReturnsFailure, (state, { error }) => ({
      ...state,
      loading: false,
      error,
    })),
    on(SalesReturnsActions.createReturn, (state) => ({ ...state, saving: true, error: null })),
    on(SalesReturnsActions.createReturnSuccess, (state, { salesReturn }) =>
      salesReturnsAdapter.addOne(salesReturn, { ...state, saving: false })
    ),
    on(SalesReturnsActions.createReturnFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    on(SalesReturnsActions.updateReturn, (state) => ({ ...state, saving: true, error: null })),
    on(SalesReturnsActions.updateReturnSuccess, (state, { salesReturn }) =>
      salesReturnsAdapter.upsertOne(salesReturn, { ...state, saving: false })
    ),
    on(SalesReturnsActions.updateReturnFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    on(SalesReturnsActions.deleteReturn, (state) => ({ ...state, saving: true, error: null })),
    on(SalesReturnsActions.deleteReturnSuccess, (state, { id }) =>
      salesReturnsAdapter.removeOne(id, { ...state, saving: false })
    ),
    on(SalesReturnsActions.deleteReturnFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Status change actions - set saving
    on(
      SalesReturnsActions.submitReturnApproval,
      SalesReturnsActions.approveReturn,
      SalesReturnsActions.rejectReturn,
      SalesReturnsActions.postReturn,
      SalesReturnsActions.cancelReturn,
      (state) => ({ ...state, saving: true, error: null })
    ),
    // Status change successes - upsertOne
    on(
      SalesReturnsActions.submitReturnApprovalSuccess,
      SalesReturnsActions.approveReturnSuccess,
      SalesReturnsActions.rejectReturnSuccess,
      SalesReturnsActions.postReturnSuccess,
      SalesReturnsActions.cancelReturnSuccess,
      (state, { salesReturn }) =>
        salesReturnsAdapter.upsertOne(salesReturn, { ...state, saving: false })
    ),
    // Status change failures
    on(
      SalesReturnsActions.submitReturnApprovalFailure,
      SalesReturnsActions.approveReturnFailure,
      SalesReturnsActions.rejectReturnFailure,
      SalesReturnsActions.postReturnFailure,
      SalesReturnsActions.cancelReturnFailure,
      (state, { error }) => ({ ...state, saving: false, error })
    ),
    on(SalesReturnsActions.clearReturnsError, (state) => ({ ...state, error: null }))
  ),
});

const { selectAll, selectEntities, selectTotal } = salesReturnsAdapter.getSelectors(
  salesReturnsFeature.selectSalesReturnsState
);

export const selectAllSalesReturns = selectAll;
export const selectSalesReturnEntities = selectEntities;
export const selectSalesReturnsTotal = selectTotal;
export const selectSalesReturnsMeta = salesReturnsFeature.selectMeta;
export const selectSalesReturnsLoading = salesReturnsFeature.selectLoading;
export const selectSalesReturnsSaving = salesReturnsFeature.selectSaving;
export const selectSalesReturnsError = salesReturnsFeature.selectError;
export const selectSalesReturnsLoaded = salesReturnsFeature.selectLoaded;
