import { createFeature, createReducer, on } from '@ngrx/store';
import { EntityState, EntityAdapter, createEntityAdapter } from '@ngrx/entity';
import { SalesCommission, SalesCommissionRule } from '../../../models/sales-commission.model';
import { PaginationMeta } from '../../../models/api.model';
import { SalesCommissionsActions } from './commissions.actions';

export interface SalesCommissionsState extends EntityState<SalesCommission> {
  meta: PaginationMeta | null;
  loading: boolean;
  saving: boolean;
  error: string | null;
  loaded: boolean;
  rules: SalesCommissionRule[];
  rulesMeta: PaginationMeta | null;
  rulesLoaded: boolean;
}

export const salesCommissionsAdapter: EntityAdapter<SalesCommission> =
  createEntityAdapter<SalesCommission>();

const initialState: SalesCommissionsState = salesCommissionsAdapter.getInitialState({
  meta: null,
  loading: false,
  saving: false,
  error: null,
  loaded: false,
  rules: [],
  rulesMeta: null,
  rulesLoaded: false,
});

export const salesCommissionsFeature = createFeature({
  name: 'salesCommissions',
  reducer: createReducer(
    initialState,
    // Load commissions
    on(SalesCommissionsActions.loadCommissions, (state, action) =>
      state.loaded && !action.force ? state : { ...state, loading: true, error: null }
    ),
    on(SalesCommissionsActions.loadCommissionsSuccess, (state, { commissions, meta }) =>
      salesCommissionsAdapter.setAll(commissions, {
        ...state,
        meta,
        loading: false,
        loaded: true,
      })
    ),
    on(SalesCommissionsActions.loadCommissionsFailure, (state, { error }) => ({
      ...state,
      loading: false,
      error,
    })),
    // Approve / Mark Paid
    on(
      SalesCommissionsActions.approveCommission,
      SalesCommissionsActions.markCommissionPaid,
      SalesCommissionsActions.bulkApproveCommissions,
      SalesCommissionsActions.bulkMarkCommissionsPaid,
      (state) => ({ ...state, saving: true, error: null })
    ),
    on(SalesCommissionsActions.approveCommissionSuccess, (state, { commission }) =>
      salesCommissionsAdapter.upsertOne(commission, { ...state, saving: false })
    ),
    on(SalesCommissionsActions.markCommissionPaidSuccess, (state, { commission }) =>
      salesCommissionsAdapter.upsertOne(commission, { ...state, saving: false })
    ),
    on(SalesCommissionsActions.bulkApproveCommissionsSuccess, (state) => ({
      ...state,
      saving: false,
    })),
    on(SalesCommissionsActions.bulkMarkCommissionsPaidSuccess, (state) => ({
      ...state,
      saving: false,
    })),
    on(
      SalesCommissionsActions.approveCommissionFailure,
      SalesCommissionsActions.markCommissionPaidFailure,
      SalesCommissionsActions.bulkApproveCommissionsFailure,
      SalesCommissionsActions.bulkMarkCommissionsPaidFailure,
      (state, { error }) => ({ ...state, saving: false, error })
    ),
    // Rules
    on(SalesCommissionsActions.loadRules, (state, action) =>
      state.rulesLoaded && !action.force ? state : { ...state, loading: true, error: null }
    ),
    on(SalesCommissionsActions.loadRulesSuccess, (state, { rules }) => ({
      ...state,
      rules,
      loading: false,
      rulesLoaded: true,
    })),
    on(SalesCommissionsActions.loadRulesFailure, (state, { error }) => ({
      ...state,
      loading: false,
      error,
    })),
    on(SalesCommissionsActions.createRule, (state) => ({ ...state, saving: true, error: null })),
    on(SalesCommissionsActions.createRuleSuccess, (state, { rule }) => ({
      ...state,
      rules: [...state.rules, rule],
      saving: false,
    })),
    on(SalesCommissionsActions.createRuleFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    on(SalesCommissionsActions.updateRule, (state) => ({ ...state, saving: true, error: null })),
    on(SalesCommissionsActions.updateRuleSuccess, (state, { rule }) => ({
      ...state,
      rules: state.rules.map((r) => (r.id === rule.id ? rule : r)),
      saving: false,
    })),
    on(SalesCommissionsActions.updateRuleFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    on(SalesCommissionsActions.deleteRule, (state) => ({ ...state, saving: true, error: null })),
    on(SalesCommissionsActions.deleteRuleSuccess, (state, { id }) => ({
      ...state,
      rules: state.rules.filter((r) => r.id !== id),
      saving: false,
    })),
    on(SalesCommissionsActions.deleteRuleFailure, (state, { error }) => ({
      ...state,
      saving: false,
      error,
    })),
    on(SalesCommissionsActions.clearCommissionsError, (state) => ({ ...state, error: null }))
  ),
});

const { selectAll, selectEntities, selectTotal } = salesCommissionsAdapter.getSelectors(
  salesCommissionsFeature.selectSalesCommissionsState
);

export const selectAllSalesCommissions = selectAll;
export const selectSalesCommissionEntities = selectEntities;
export const selectSalesCommissionsTotal = selectTotal;
export const selectSalesCommissionsMeta = salesCommissionsFeature.selectMeta;
export const selectSalesCommissionsLoading = salesCommissionsFeature.selectLoading;
export const selectSalesCommissionsSaving = salesCommissionsFeature.selectSaving;
export const selectSalesCommissionsError = salesCommissionsFeature.selectError;
export const selectSalesCommissionsLoaded = salesCommissionsFeature.selectLoaded;
export const selectSalesCommissionRules = salesCommissionsFeature.selectRules;
export const selectSalesCommissionRulesMeta = salesCommissionsFeature.selectRulesMeta;
export const selectSalesCommissionRulesLoaded = salesCommissionsFeature.selectRulesLoaded;
