import { createFeature, createReducer, on } from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { ProductCategory } from '../../models/product-category.model';
import { PaginationMeta } from '../../models/api.model';
import { ProductCategoriesActions } from './product-categories.actions';

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

export const productCategoriesAdapter: EntityAdapter<ProductCategory> = createEntityAdapter<ProductCategory>();

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

export const productCategoriesFeature = createFeature({
  name: 'productCategories',
  reducer: createReducer(
    initialState,
    // Load
    on(ProductCategoriesActions.loadProductCategories, (state, action) =>
      state.loaded && !action.forceReload ? state : {
        ...state,
        loading: true,
        error: null,
      }
    ),
    on(ProductCategoriesActions.loadProductCategoriesSuccess, (state, { categories, meta }) =>
      productCategoriesAdapter.setAll(categories, { ...state, meta, loading: false, loaded: true })
    ),
    on(ProductCategoriesActions.loadProductCategoriesFailure, (state, { error }) => ({
      ...state,
      loading: false,
      error,
    })),
    // Create
    on(ProductCategoriesActions.createProductCategory, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(ProductCategoriesActions.createProductCategorySuccess, (state, { category }) =>
      productCategoriesAdapter.addOne(category, { ...state, saving: false })
    ),
    on(ProductCategoriesActions.createProductCategoryFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Update
    on(ProductCategoriesActions.updateProductCategory, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(ProductCategoriesActions.updateProductCategorySuccess, (state, { category }) =>
      productCategoriesAdapter.upsertOne(category, { ...state, saving: false })
    ),
    on(ProductCategoriesActions.updateProductCategoryFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Delete
    on(ProductCategoriesActions.deleteProductCategory, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(ProductCategoriesActions.deleteProductCategorySuccess, (state, { id }) =>
      productCategoriesAdapter.removeOne(id, { ...state, saving: false })
    ),
    on(ProductCategoriesActions.deleteProductCategoryFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Clear Error
    on(ProductCategoriesActions.clearProductCategoriesError, (state) => ({
      ...state,
      error: null,
    }))
  ),
});

const { selectAll, selectEntities, selectTotal } = productCategoriesAdapter.getSelectors(productCategoriesFeature.selectProductCategoriesState);

export const selectAllProductCategories = selectAll;
export const selectProductCategoryEntities = selectEntities;
export const selectProductCategoriesTotal = selectTotal;
export const selectProductCategoriesMeta = productCategoriesFeature.selectMeta;
export const selectProductCategoriesLoading = productCategoriesFeature.selectLoading;
export const selectProductCategoriesSaving = productCategoriesFeature.selectSaving;
export const selectProductCategoriesError = productCategoriesFeature.selectError;
export const selectProductCategoriesLoaded = productCategoriesFeature.selectLoaded;
