import { Risk } from 'client/Containers/Calculation/Components/FinGAP/types';
import CoreService from 'core/services/CoreService';
import * as FinGAP from 'core/services/CoreService/types/Cerebellum/finGAP';
import { ICalculationStore } from 'core/types/Calculation/Store';
import { comparer, reaction } from 'mobx';
import { ElementStatus } from 'types/elements';

export function commonReactions(calculationStore: ICalculationStore) {
  // Расчет итоговой суммы ФинГАП и запись в таблицу страхования
  reaction(
    () => {
      const { $finGAP } = calculationStore.stores;
      return $finGAP.totalSum();
    },
    totalSum => {
      calculationStore.setTableRow('tableInsurance', rows =>
        rows.findIndex(x => x?.key === 'finGAP'),
      )({
        insCost: { value: totalSum },
      });
    },
  );

  /**
Реакция на изменение Страховой компании у ФинГАП и Срока лизинга:

Если Страхованя компания = Не выбрано, то
     
Плательщик insuredFinGAP = ЛП (100 000 000) и закрыто для редактирования,
Стоимость за первый период inscostFinGAP = 0
Срок страхования insTermFinGAP  = 12 мес (100 000 000) и закрыто для редактирования
иначе 

Плательщик insuredFinGAP = открыто для редактирования,
Стоимость за первый период inscostFinGAP = 0
Срок страхования insTermFinGAP  = Если срок лизинга tbxLeasingPeriod < 13, то указываем Срок страхования  insTermFinGAP  =12 мес и закрываем для редактирования, иначе открыто для редактирования
   */
  reaction(
    () => {
      const { rows: insuranceRows } = calculationStore.tables.tableInsurance;
      const finGAPRow = insuranceRows.find(x => x.key === 'finGAP');
      const insuranceCompany = finGAPRow?.insuranceCompany?.value;

      const { leasingPeriod } = calculationStore.values;

      return {
        insuranceCompany,
        leasingPeriod,
      };
    },
    ({ insuranceCompany, leasingPeriod }) => {
      if (!insuranceCompany) {
        calculationStore.setTableRow('tableInsurance', rows =>
          rows.findIndex(x => x?.key === 'finGAP'),
        )({
          insured: { value: 100000000, status: ElementStatus.Disabled },
          insCost: { value: 0 },
          insTerm: { value: 100000000, status: ElementStatus.Disabled },
        });
      } else {
        calculationStore.setTableRow('tableInsurance', rows =>
          rows.findIndex(x => x?.key === 'finGAP'),
        )({
          insured: { status: ElementStatus.Default },
          // insCost: { value: 0 },
          insTerm:
            leasingPeriod < 13
              ? { value: 100000000, status: ElementStatus.Disabled }
              : { status: ElementStatus.Default },
        });
      }
    },
    {
      equals: comparer.shallow,
    },
  );

  // Заполнение таблицы рисков ФинГАП
  reaction(
    () => {
      const { rows: insuranceRows } = calculationStore.tables.tableInsurance;
      const finGAPRow = insuranceRows.find(x => x.key === 'finGAP');
      const insuranceCompany = finGAPRow?.insuranceCompany?.value;
      return insuranceCompany;
    },
    insuranceCompany => {
      const { $finGAP } = calculationStore.stores;

      if (!insuranceCompany) {
        $finGAP.clear();
        return;
      }

      const add_product_types = calculationStore.getStaticData(
        'evo_addproduct_type',
      );

      const risks = add_product_types
        .filter(
          x =>
            x.evo_accountid === insuranceCompany &&
            x.evo_product_type === 100_000_006,
        )
        .map(
          x =>
            ({
              key: x.evo_addproduct_typeid,
              riskId: x.evo_addproduct_typeid,
              riskName: x.evo_name,
              calcType: x.evo_type_calc_cerebellum,
              premiumPerc: x.evo_cost_service_provider_withoutnds,
              sum: 0,
              premium: 0,
              keys: x.evo_addproduct_types?.map(x => x.evo_addproduct_typeid),
            } as Risk),
        );

      $finGAP.setRisks(risks);
    },
  );

  // Запрос расчета финГАП в мозжечок
  reaction(
    () => {
      const { rows: insuranceRows } = calculationStore.tables.tableInsurance;
      const finGAPRow = insuranceRows.find(x => x.key === 'finGAP');
      const insuranceCompany = finGAPRow?.insuranceCompany?.value;

      const paymentsRows = calculationStore.tables.tablePayments.rows;
      const payments: FinGAP.PaymentRow[] = paymentsRows.map(x => ({
        percentPayment: x.paymentRelation?.value,
      }));

      // TODO: types for CalculationStore ComputedValues
      //@ts-ignore
      const plPrice = calculationStore.plPriceRub();
      //@ts-ignore
      const discount = calculationStore.discountRub();
      const { firstPaymentRub, leasingPeriod } = calculationStore.values;

      return {
        payments,
        insuranceCompany,
        plPrice,
        discount,
        leasingPeriod,
        firstPaymentRub,
      };
    },
    ({
      payments,
      insuranceCompany,
      plPrice,
      discount,
      leasingPeriod,
      firstPaymentRub,
    }) => {
      if (!insuranceCompany) return;

      const requestValues: FinGAP.RequestFinGAP['values'] = {
        plPrice,
        discount,
        firstPayment: firstPaymentRub,
        leasingPeriod,
        premiumPerc: 0,
      };

      const { $finGAP } = calculationStore.stores;
      const requests = $finGAP.risks.map(x =>
        CoreService.finGAP({
          calcType: x.calcType,
          payments,
          values: { ...requestValues, premiumPerc: x.premiumPerc },
        }),
      );
      Promise.all(requests).then(results => {
        const risks = $finGAP.risks.map((x, i) => ({
          ...x,
          sum: results[i].sum,
          premium: results[i].premium,
        }));
        $finGAP.setRisks(risks);
      });
    },
    {
      equals: comparer.structural,
      // Important: delay prohibits multiple reaction invocation
      delay: 100,
    },
  );
}
