import { pipe } from 'fp-ts/lib/function';
import * as O from 'fp-ts/Option';
import produce from 'immer';
import { withMinimalDuration } from '../../../../../utils/promise';
import benefitsApi from '../../../apis/benefits-api/benefits.api';
import { BenefitItemDto } from '../../../apis/benefits-api/benefits-api.dto';
import manageBenefitsApi from '../api/manage-benefits.api';
import { AccountBenefitWithIdDto } from '../api/manage-benefits-api.dto';
import manageBenefitsQuery from '../store/manage-benefits.query';
import manageBenefitsStore from '../store/manage-benefits.store';
export class EditBenefitService {
  async loadExistingBenefitForEditingAsync(benefitId) {
    manageBenefitsStore.update((state) => {
      state.selectedBenefit = O.none;
    });
    manageBenefitsStore.setLoading(true);
    const existingBenefit = AccountBenefitWithIdDto.toBenefit(await manageBenefitsApi.loadBenefitForEditingAsync(benefitId));
    manageBenefitsStore.update((state) => {
      state.selectedBenefit = O.some(existingBenefit);
      state.draftBenefit = O.some(this.existingBenefitToDraft(existingBenefit));
    });
    manageBenefitsStore.setLoading(false);
  }
  createDraftBenefit() {
    const newDraft = {
      title: O.none,
      category: O.none,
      subtitle: O.none,
      description: O.none,
      url: O.none,
      attachment: O.none,
      icon: O.none,
      isValid: false,
      isDirty: false
    };
    manageBenefitsStore.update((state) => {
      state.selectedBenefit = O.none;
      state.draftBenefit = O.some(newDraft);
    });
  }
  clearDraftBenefit() {
    manageBenefitsStore.update((state) => {
      state.draftBenefit = O.none;
    });
  }
  updateDraftBenefit(newDraft) {
    manageBenefitsStore.update((state) => {
      state.draftBenefit = O.some(newDraft);
    });
  }
  async publishDraftBenefitAsync() {
    const draftBenefit = manageBenefitsQuery.getValue().draftBenefit;
    if (O.isNone(draftBenefit)) {
      return;
    }
    this.assertDraftIsValid(draftBenefit.value);
    manageBenefitsStore.setLoading(true);
    const selectedBenefit = manageBenefitsQuery.getValue().selectedBenefit;
    if (O.isSome(selectedBenefit)) {
      const updateBenefitCommandDto = {
        updateAccountBenefit: BenefitItemDto.fromDraftBenefit(draftBenefit.value)
      };
      await manageBenefitsApi.postCommandAsync(selectedBenefit.value.id, updateBenefitCommandDto);
    }
    else {
      const createBenefitCommmandDto = {
        createAccountBenefit: BenefitItemDto.fromDraftBenefit(draftBenefit.value)
      };
      await manageBenefitsApi.postCommandAsync(O.none, createBenefitCommmandDto);
    }
    manageBenefitsStore.setLoading(false);
  }
  async deleteSelectedBenefitAsync() {
    const selectedBenefit = manageBenefitsQuery.getValue().selectedBenefit;
    if (O.isSome(selectedBenefit)) {
      manageBenefitsStore.setLoading(true);
      await manageBenefitsApi.postCommandAsync(selectedBenefit.value.id, 'deleteAccountBenefit');
      manageBenefitsStore.setLoading(false);
    }
  }
  updateDraftUrl(url) {
    this.updateDraft((draft) => {
      draft.url = O.fromNullable(url);
      draft.isDirty = true;
    });
  }
  clearDraftUrl() {
    this.updateDraft((draft) => {
      draft.url = O.none;
      draft.isDirty = true;
    });
  }
  async uploadAttachmentAsync(file) {
    manageBenefitsStore.setLoading(true);
    try {
      const attachmentProperties = await withMinimalDuration(benefitsApi.postDocumentAsync({ file }), 500);
      this.updateDraft((draft) => {
        draft.attachment = O.some(attachmentProperties);
        draft.isDirty = true;
      });
    }
    finally {
      manageBenefitsStore.setLoading(false);
    }
  }
  clearAttachment() {
    this.updateDraft((draft) => {
      draft.attachment = O.none;
      draft.isDirty = true;
    });
  }
  async uploadIconAsync(file) {
    manageBenefitsStore.setLoading(true);
    try {
      const attachmentProperties = await withMinimalDuration(benefitsApi.postIconAsync({ file }), 500);
      this.updateDraft((draft) => {
        draft.icon = O.some(attachmentProperties);
        draft.isDirty = true;
      });
    }
    finally {
      manageBenefitsStore.setLoading(false);
    }
  }
  clearIcon() {
    this.updateDraft((draft) => {
      draft.icon = O.none;
      draft.isDirty = true;
    });
  }
  assertDraftIsValid(draft) {
    const isDraftValid = O.isSome(draft.title) && O.isSome(draft.category);
    if (!isDraftValid)
      throw Error('Draft benefit is not valid');
  }
  updateDraft(producer) {
    manageBenefitsStore.update((state) => {
      state.draftBenefit = pipe(state.draftBenefit, O.map(produce(producer)));
    });
  }
  existingBenefitToDraft(existingBenefit) {
    return {
      title: existingBenefit.title,
      category: existingBenefit.category,
      subtitle: existingBenefit.subtitle,
      description: existingBenefit.description,
      url: existingBenefit.url,
      attachment: existingBenefit.attachment,
      icon: existingBenefit.icon,
      isValid: true,
      isDirty: false
    };
  }
}
export default new EditBenefitService();
