import { createFeature, createReducer, on } from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { SalesQuotation } from '../../../models/sales-quotation.model';
import { PaginationMeta } from '../../../models/api.model';
import { SalesQuotationsActions } from './quotations.actions';

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

export const salesQuotationsAdapter: EntityAdapter<SalesQuotation> =
  createEntityAdapter<SalesQuotation>();

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

export const salesQuotationsFeature = createFeature({
  name: 'salesQuotations',
  reducer: createReducer(
    initialState,
    on(SalesQuotationsActions.loadQuotations, (state, action) =>
      state.loaded && !action.force ? state : { ...state, loading: true, error: null }
    ),
    on(SalesQuotationsActions.loadQuotationsSuccess, (state, { quotations, meta }) =>
      salesQuotationsAdapter.setAll(quotations, { ...state, meta, loading: false, loaded: true })
    ),
    on(SalesQuotationsActions.loadQuotationsFailure, (state, { error }) => ({
      ...state,
      loading: false,
      error,
    })),
    on(SalesQuotationsActions.createQuotation, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(SalesQuotationsActions.createQuotationSuccess, (state, { quotation }) =>
      salesQuotationsAdapter.addOne(quotation, { ...state, saving: false })
    ),
    on(SalesQuotationsActions.createQuotationFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    on(SalesQuotationsActions.updateQuotation, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(SalesQuotationsActions.updateQuotationSuccess, (state, { quotation }) =>
      salesQuotationsAdapter.upsertOne(quotation, { ...state, saving: false })
    ),
    on(SalesQuotationsActions.updateQuotationFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    on(SalesQuotationsActions.deleteQuotation, (state) => ({
      ...state,
      saving: true,
      error: null,
    })),
    on(SalesQuotationsActions.deleteQuotationSuccess, (state, { id }) =>
      salesQuotationsAdapter.removeOne(id, { ...state, saving: false })
    ),
    on(SalesQuotationsActions.deleteQuotationFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    // Status change actions - set saving
    on(
      SalesQuotationsActions.sendQuotation,
      SalesQuotationsActions.acceptQuotation,
      SalesQuotationsActions.rejectQuotation,
      SalesQuotationsActions.convertQuotationToOrder,
      SalesQuotationsActions.convertQuotationToInvoice,
      SalesQuotationsActions.cancelQuotation,
      SalesQuotationsActions.duplicateQuotation,
      (state) => ({ ...state, saving: true, error: null })
    ),
    // Status change successes - upsertOne
    on(
      SalesQuotationsActions.sendQuotationSuccess,
      SalesQuotationsActions.acceptQuotationSuccess,
      SalesQuotationsActions.rejectQuotationSuccess,
      SalesQuotationsActions.convertQuotationToOrderSuccess,
      SalesQuotationsActions.convertQuotationToInvoiceSuccess,
      SalesQuotationsActions.cancelQuotationSuccess,
      (state, { quotation }) =>
        salesQuotationsAdapter.upsertOne(quotation, { ...state, saving: false })
    ),
    on(SalesQuotationsActions.duplicateQuotationSuccess, (state, { quotation }) =>
      salesQuotationsAdapter.addOne(quotation, { ...state, saving: false })
    ),
    // Status change failures
    on(
      SalesQuotationsActions.sendQuotationFailure,
      SalesQuotationsActions.acceptQuotationFailure,
      SalesQuotationsActions.rejectQuotationFailure,
      SalesQuotationsActions.convertQuotationToOrderFailure,
      SalesQuotationsActions.convertQuotationToInvoiceFailure,
      SalesQuotationsActions.cancelQuotationFailure,
      SalesQuotationsActions.duplicateQuotationFailure,
      (state, { error }) => ({ ...state, saving: false, error })
    ),
    on(SalesQuotationsActions.clearQuotationsError, (state) => ({ ...state, error: null }))
  ),
});

const { selectAll, selectEntities, selectTotal } = salesQuotationsAdapter.getSelectors(
  salesQuotationsFeature.selectSalesQuotationsState
);

export const selectAllSalesQuotations = selectAll;
export const selectSalesQuotationEntities = selectEntities;
export const selectSalesQuotationsTotal = selectTotal;
export const selectSalesQuotationsMeta = salesQuotationsFeature.selectMeta;
export const selectSalesQuotationsLoading = salesQuotationsFeature.selectLoading;
export const selectSalesQuotationsSaving = salesQuotationsFeature.selectSaving;
export const selectSalesQuotationsError = salesQuotationsFeature.selectError;
export const selectSalesQuotationsLoaded = salesQuotationsFeature.selectLoaded;
