import { createReducer, on } from '@ngrx/store';
import { initialCheckoutState, storeCheckoutAdapter } from './domain-checkout.state';

import * as DomainCheckoutActions from './domain-checkout.actions';
import { Dictionary } from '@ngrx/entity';
import { CheckoutEntity } from './defs/checkout.entity';
import { isNullOrUndefined } from '@utils/common';

const _domainCheckoutReducer = createReducer(
  initialCheckoutState,
  on(DomainCheckoutActions.setShoppingCart, (s, { processId, shoppingCart }) => {
    const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
    entity.shoppingCart = shoppingCart;
    return storeCheckoutAdapter.setOne(entity, s);
  }),
  on(DomainCheckoutActions.setCheckout, (s, { processId, checkout }) => {
    const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
    entity.checkout = checkout;
    return storeCheckoutAdapter.setOne(entity, s);
  }),
  on(DomainCheckoutActions.setBuyerCommunicationDetails, (s, { processId, email, mobile }) => {
    const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
    const communicationDetails = { ...entity.buyer.communicationDetails };
    communicationDetails.email = email || communicationDetails.email;
    communicationDetails.mobile = mobile || communicationDetails.mobile;
    entity.buyer = {
      ...entity.buyer,
      communicationDetails,
    };
    return storeCheckoutAdapter.setOne(entity, s);
  }),
  on(DomainCheckoutActions.setNotificationChannels, (s, { processId, notificationChannels }) => {
    const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
    return storeCheckoutAdapter.setOne({ ...entity, notificationChannels }, s);
  }),
  on(DomainCheckoutActions.setCheckoutDestination, (s, { processId, destination }) => {
    const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
    entity.checkout = {
      ...entity.checkout,
      destinations: entity.checkout.destinations.map((dest) => {
        if (dest.id === destination.id) {
          return { ...dest, ...destination };
        }
        return { ...dest };
      }),
    };
    return storeCheckoutAdapter.setOne(entity, s);
  }),
  on(DomainCheckoutActions.setCustomerFeatures, (s, { processId, customerFeatures }) => {
    const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
    entity.customerFeatures = customerFeatures;
    return storeCheckoutAdapter.setOne(entity, s);
  }),
  on(DomainCheckoutActions.setShippingAddress, (s, { processId, shippingAddress }) => {
    const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
    entity.shippingAddress = shippingAddress;
    return storeCheckoutAdapter.setOne(entity, s);
  }),
  on(DomainCheckoutActions.setBuyer, (s, { processId, buyer }) => {
    const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
    entity.buyer = buyer;
    return storeCheckoutAdapter.setOne(entity, s);
  }),
  on(DomainCheckoutActions.setPayer, (s, { processId, payer }) => {
    const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
    entity.payer = payer;
    return storeCheckoutAdapter.setOne(entity, s);
  }),
  on(DomainCheckoutActions.setSpecialComment, (s, { processId, agentComment }) => {
    const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
    entity.specialComment = agentComment;
    return storeCheckoutAdapter.setOne(entity, s);
  }),
  on(DomainCheckoutActions.removeProcess, (s, { processId }) => storeCheckoutAdapter.removeOne(processId, s)),
  on(DomainCheckoutActions.setOrders, (s, { orders }) => ({ ...s, orders: [...s.orders, ...orders] })),
  on(DomainCheckoutActions.removeAllOrders, (s) => ({
    ...s,
    orders: [],
  })),
  on(DomainCheckoutActions.setOlaError, (s, { processId, olaErrorIds }) => {
    const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
    entity.olaErrorIds = olaErrorIds;
    return storeCheckoutAdapter.setOne(entity, s);
  })
);

export function domainCheckoutReducer(state, action) {
  return _domainCheckoutReducer(state, action);
}

function getOrCreateCheckoutEntity({ entities, processId }: { entities: Dictionary<CheckoutEntity>; processId: number }): CheckoutEntity {
  let entity = entities[processId];

  if (isNullOrUndefined(entity)) {
    return {
      processId,
      checkout: undefined,
      shoppingCart: undefined,
      customerFeatures: undefined,
      shippingAddress: undefined,
      orders: [],
      payer: undefined,
      buyer: undefined,
      specialComment: '',
      notificationChannels: 0,
      olaErrorIds: [],
    };
  }

  return { ...entity };
}
