import { gql } from '@apollo/client';
import { getValueName } from 'client/Containers/Calculation/Elements/tools';
import { ElementsNames } from 'client/Containers/Calculation/types/elements';
import { openNotification } from 'client/Elements/Notification';
import _1CService from 'core/services/1CService';
import CrmService from 'core/services/CrmService';
import { IEvoTown } from 'core/services/CrmService/types/entities';
import { currentDate } from 'core/tools/date';
import { IReactionEffect } from 'core/types/Calculation/Store/effect';
import { Process } from 'core/types/Calculation/Store/process';
import { get } from 'lodash';
import { ElementStatus } from 'types/elements';

//TODO: beautify
const v = {
  tbxVehicleTaxInYear: { value: 0, validator: value => value === 0 },
  radioTypePTS: { value: null, validator: value => value === null },
  // selectObjectRegionRegistration: {
  //   value: null,
  //   validator: value => value === null,
  // },
};

const gibddReactions: IReactionEffect[] = [
  calculationStore => ({
    expression: () => {
      return calculationStore.getOption('selectLeaseObjectType');
    },
    effect: leaseObjectType => {
      if (['6', '9', '10', '11'].includes(leaseObjectType.evo_id)) {
        calculationStore.setStatus(
          'radioObjectRegistration',
          ElementStatus.Disabled,
        );
        calculationStore.setValue('objectRegistration', 100000000);
      } else {
        calculationStore.setStatus(
          'radioObjectRegistration',
          ElementStatus.Default,
        );
      }
    },
    options: {
      fireImmediately: true,
    },
  }),

  ...(Object.keys(v) as ElementsNames[]).map(elementName => {
    const valueName = getValueName(elementName);
    const value = v[elementName].value;
    const validator = v[elementName].validator;

    return calculationStore => ({
      expression: () => {
        return calculationStore.getValues([valueName, 'objectRegistration']);
      },
      effect: values => {
        calculationStore.setValidation(elementName, undefined);
        if (values.objectRegistration === 100000001) {
          calculationStore.setStatus(elementName, ElementStatus.Default);
          calculationStore.setValidation(
            elementName,
            !validator(values[valueName]),
          );
        } else {
          calculationStore.setStatus(elementName, ElementStatus.Disabled);
          calculationStore.setValue(valueName, value);
        }
      },
      options: {
        fireImmediately: true,
      },
    });
  }),

  calculationStore => ({
    expression: () => {
      return calculationStore.getValues(['leasingPeriod', 'vehicleTaxInYear']);
    },
    effect: ({ vehicleTaxInYear, leasingPeriod }) => {
      if (vehicleTaxInYear > 0) {
        calculationStore.setValue(
          'vehicleTaxInLeasingPeriod',
          (vehicleTaxInYear / 12) * leasingPeriod,
        );
      } else {
        calculationStore.setValue('vehicleTaxInLeasingPeriod', 0);
      }
    },
    options: {
      fireImmediately: true,
    },
  }),

  (calculationStore, calculationProcess) => ({
    expression: () => {
      return calculationStore.getValues([
        'leaseObjectType',
        'objectCategoryTax',
        'objectRegistration',
      ]);
    },
    effect: ({ objectRegistration, objectCategoryTax }) => {
      if (calculationProcess.hasProcess(Process.LoadKp)) {
        return;
      }
      if (objectRegistration === 100000001) {
        if ([100000006, 100000009].includes(objectCategoryTax)) {
          calculationStore.setValue('objectTypeTax', 100000002);
        } else {
          const leaseObjectType = calculationStore.getOption(
            'selectLeaseObjectType',
          );
          if (leaseObjectType && leaseObjectType.evo_vehicle_type_tax) {
            calculationStore.setValue(
              'objectTypeTax',
              leaseObjectType.evo_vehicle_type_tax,
            );
          }
        }
      } else {
        calculationStore.setValue('objectTypeTax', null);
      }
    },
    options: {
      fireImmediately: true,
    },
  }),

  calculationStore => ({
    expression: () => {
      return calculationStore.getValues(['leaseObjectCategory', 'maxMass']);
    },
    effect: ({ leaseObjectCategory, maxMass }) => {
      calculationStore.setValidation('tbxMaxMass', undefined);
      switch (leaseObjectCategory) {
        case 100000001: {
          if (maxMass > 3500) {
            calculationStore.setValidation('tbxMaxMass', false);
            openNotification({
              type: 'error',
              message: 'Ошибка',
              description:
                'При категории ТС = В Разерешенная макс.масс не может быть больше 3500кг',
            });
          }
          break;
        }
        case 100000002: {
          if (maxMass <= 3500) {
            calculationStore.setValidation('tbxMaxMass', false);
            openNotification({
              type: 'error',
              message: 'Ошибка',
              description: 'Разерешенная макс.масс не может быть меньше 3500кг',
            });
          }
          break;
        }
      }
    },
    options: {
      fireImmediately: true,
    },
  }),

  calculationStore => ({
    expression: () => {
      return calculationStore.getOption('selectLeaseObjectType');
    },
    effect: selectLeaseObjectType => {
      calculationStore.setValue(
        'leaseObjectCategory',
        selectLeaseObjectType?.evo_category,
      );
    },
    options: {
      fireImmediately: true,
    },
  }),

  calculationStore => ({
    expression: () => {
      return calculationStore.getValues([
        'leaseObjectType',
        'leaseObjectCategory',
        'typePTS',
        'objectRegistration',
      ]);
    },
    effect: ({ leaseObjectCategory, typePTS, objectRegistration }) => {
      calculationStore.setStatus(
        'selectObjectCategoryTax',
        ElementStatus.Disabled,
      );
      if (objectRegistration === 100000001 && typePTS === 100000001) {
        calculationStore.setStatus(
          'selectObjectCategoryTax',
          ElementStatus.Default,
        );
        const leaseObjectType = calculationStore.getOption(
          'selectLeaseObjectType',
        );
        if (leaseObjectCategory === leaseObjectType?.evo_category) {
          calculationStore.setFilter('selectObjectCategoryTax', options =>
            options.filter(option =>
              //@ts-ignore
              leaseObjectType?.evo_category_tr?.includes(option.value),
            ),
          );
        }
      } else {
        calculationStore.setValue('objectCategoryTax', null);
      }
    },
  }),

  calculationStore => ({
    expression: () => {
      return {
        ...calculationStore.getValues([
          'typePTS',
          'objectRegistration',
          'objectCategoryTax',
        ]),
        leaseObjectType: calculationStore.getOption('selectLeaseObjectType'),
      };
    },
    effect: ({
      leaseObjectType,
      typePTS,
      objectRegistration,
      objectCategoryTax,
    }) => {
      if (
        objectRegistration === 100000001 &&
        typePTS === 100000001 &&
        objectCategoryTax === null &&
        leaseObjectType &&
        leaseObjectType.evo_category_tr &&
        leaseObjectType.evo_category_tr.length
      ) {
        calculationStore.setValidation('selectObjectCategoryTax', false);
        openNotification({
          type: 'error',
          message: 'Ошибка',
          description:
            'Необходимо из ЭПТС указать Категорию в соответствии с ТР ТС 018/2011',
        });
      } else {
        calculationStore.setValidation('selectObjectCategoryTax', undefined);
      }
    },
  }),

  calculationStore => ({
    expression: () => {
      return {
        leaseObjectType: calculationStore.getOption('selectLeaseObjectType'),
        ...calculationStore.getValues(['insNSIB']),
      };
    },
    effect: ({ leaseObjectType }) => {
      if (
        leaseObjectType.evo_id === '11' &&
        calculationStore.getValue('insNSIB') === null
      ) {
        calculationStore.setValidation('selectInsNSIB', false);
        openNotification({
          type: 'error',
          message: 'Ошибка',
          description: 'Страхование НСИБ обязательно для мотоциклистов',
        });
      } else {
        calculationStore.setValidation('selectInsNSIB', undefined);
      }
    },
  }),

  (calculationStore, calculationProcess) => ({
    expression: () => {
      return calculationStore.getValues([
        'objectRegistration',
        'objectTypeTax',
        'regionRegistration',
        'leaseObjectYear',
        'leaseObjectMotorPower',
      ]);
    },
    effect: ({
      objectRegistration,
      objectTypeTax,
      regionRegistration,
      leaseObjectYear,
      leaseObjectMotorPower,
    }) => {
      if (calculationProcess.hasProcess(Process.LoadKp)) {
        return;
      }
      if (
        objectRegistration === null ||
        objectRegistration !== 100000001 ||
        objectTypeTax === null ||
        regionRegistration === null ||
        leaseObjectYear === 0 ||
        leaseObjectMotorPower === 0
      ) {
        calculationStore.setValue('vehicleTaxInYear', 0);
        return;
      }

      calculationStore.setStatus('tbxVehicleTaxInYear', ElementStatus.Loading);
      const regionRegistrationOption = calculationStore.getOption(
        'selectRegionRegistration',
      );
      const objectTypeTaxOption = calculationStore.getOption(
        'selectObjectTypeTax',
      );
      _1CService.leasingTrial
        .getTransTax({
          calcDate: currentDate,
          power: leaseObjectMotorPower,
          year: leaseObjectYear,
          OKTMO: regionRegistrationOption?.evo_oktmo || '',
          //@ts-ignore
          carCategory: objectTypeTaxOption.type,
        })
        .then(res => {
          calculationStore.setValue('vehicleTaxInYear', res.tax || 0);
        })
        .finally(() => {
          calculationStore.setStatus(
            'tbxVehicleTaxInYear',
            ElementStatus.Default,
          );
        });
    },
  }),

  calculationStore => ({
    expression: () => {
      const objectRegionRegistration = calculationStore.getOption(
        'selectObjectRegionRegistration',
      );

      return {
        objectRegionRegistration,
        ...calculationStore.getValues([
          'objectRegistration',
          'regionRegistration',
          'typePTS',
          'leaseObjectCategory',
          'leaseObjectType',
        ]),
      };
    },
    effect: ({
      objectRegistration,
      objectRegionRegistration,
      regionRegistration,
      typePTS,
      leaseObjectCategory,
      leaseObjectType,
    }) => {
      calculationStore.setFilter('selectRegistration', options =>
        options.filter(x => {
          if (
            !x.evo_leasingobject_types?.find(
              x => x.evo_leasingobject_typeid === leaseObjectType,
            )
          ) {
            return false;
          }

          if (!objectRegionRegistration && !regionRegistration) {
            return false;
          }

          if (!(x?.evo_whom_register === objectRegistration)) {
            return false;
          }

          if (leaseObjectCategory !== 100000001 && x?.evo_towtruck) {
            return false;
          }

          if (
            !(
              x?.evo_gibdd_region ===
              (objectRegionRegistration?.evo_regionid === regionRegistration)
            )
          ) {
            return false;
          }

          if (
            (typePTS &&
              (!x?.evo_pts_type ||
                x?.evo_pts_type.filter(t => t > 0).length === 0)) ||
            x?.evo_pts_type?.filter(t => t > 0).includes(typePTS) === false
          ) {
            return false;
          }

          if (!x?.evo_accountid) {
            return true;
          }

          return objectRegionRegistration?.accounts
            ?.map(r => r.accountid)
            .includes(x.evo_accountid);
        }),
      );
    },
    options: {
      fireImmediately: true,
    },
  }),

  (calculationStore, calculationProcess) => ({
    expression: () => {
      return {
        lead: calculationStore.getOption('selectLead'),
        opportunity: calculationStore.getOption('selectOpportunity'),
      };
    },
    effect: ({ lead, opportunity }) => {
      if (calculationProcess.hasProcess(Process.LoadKp)) {
        return;
      }
      const evo_region_fias_id = get(
        lead?.accountidData || opportunity?.accountidData,
        'evo_address_legalidData.evo_region_fias_id',
        undefined,
      );

      if (evo_region_fias_id) {
        const region = calculationStore.getOption('selectLegalClientRegion', {
          evo_fias_id: evo_region_fias_id,
        });
        calculationStore.setValue('legalClientRegion', region?.evo_regionid);
        calculationStore.setStatus(
          'selectLegalClientRegion',
          ElementStatus.Disabled,
        );
      } else {
        calculationStore.setValue('legalClientRegion', null);
        calculationStore.setStatus(
          'selectLegalClientRegion',
          ElementStatus.Default,
        );
      }
    },
  }),

  (calculationStore, calculationProcess) => ({
    expression: () => {
      return {
        lead: calculationStore.getOption('selectLead'),
        opportunity: calculationStore.getOption('selectOpportunity'),
      };
    },
    effect: ({ lead, opportunity }) => {
      if (calculationProcess.hasProcess(Process.LoadKp)) {
        return;
      }
      const evo_city_fias_id = get(
        lead?.accountidData || opportunity?.accountidData,
        'evo_address_legalidData.evo_city_fias_id',
        undefined,
      );

      if (evo_city_fias_id) {
        CrmService.getCRMEntities<'evo_town', IEvoTown>({
          query: gql`
            query legalClientTown($evo_fias_id: String) {
              evo_town(evo_fias_id: $evo_fias_id) {
                evo_fias_id
                evo_townid
              }
            }
          `,
          variables: {
            evo_fias_id: evo_city_fias_id,
          },
        }).then(({ evo_town }) => {
          if (evo_town) {
            calculationStore.setValue('legalClientTown', evo_town.evo_townid);
            calculationStore.setStatus(
              'selectLegalClientTown',
              ElementStatus.Disabled,
            );
          }
        });
      } else {
        calculationStore.setValue('legalClientTown', null);
        calculationStore.setStatus(
          'selectLegalClientTown',
          ElementStatus.Default,
        );
      }
    },
  }),

  (calculationStore, calculationProcess) => ({
    expression: () => {
      return {
        lead: calculationStore.getOption('selectLead'),
        opportunity: calculationStore.getOption('selectOpportunity'),
        objectRegistration: calculationStore.getValue('objectRegistration'),
      };
    },
    effect: ({ lead, opportunity, objectRegistration }) => {
      if (calculationProcess.hasProcess(Process.LoadKp)) {
        return;
      }
      if (objectRegistration === 100000001) {
        calculationStore.setFilter('selectRegionRegistration', regions =>
          regions.filter(x => x.evo_businessunit_evolution === true),
        );
        calculationStore.setStatus(
          'selectRegionRegistration',
          ElementStatus.Default,
        );
      } else {
        calculationStore.setFilter('selectRegionRegistration', undefined);

        const evo_region_fias_id = get(
          lead?.accountidData || opportunity?.accountidData,
          'evo_address_legalidData.evo_region_fias_id',
          undefined,
        );

        if (evo_region_fias_id) {
          const region = calculationStore.getOption(
            'selectRegionRegistration',
            {
              evo_fias_id: evo_region_fias_id,
            },
          );
          calculationStore.setValue('regionRegistration', region?.evo_regionid);
          calculationStore.setStatus(
            'selectRegionRegistration',
            ElementStatus.Disabled,
          );
        } else {
          calculationStore.setValue('regionRegistration', null);
          calculationStore.setStatus(
            'selectRegionRegistration',
            ElementStatus.Default,
          );
        }
      }
    },
  }),

  (calculationStore, calculationProcess) => ({
    expression: () => {
      return {
        lead: calculationStore.getOption('selectLead'),
        opportunity: calculationStore.getOption('selectOpportunity'),
        objectRegistration: calculationStore.getValue('objectRegistration'),
      };
    },
    effect: ({ lead, opportunity, objectRegistration }) => {
      if (calculationProcess.hasProcess(Process.LoadKp)) {
        return;
      }

      const evo_city_fias_id = get(
        lead?.accountidData || opportunity?.accountidData,
        'evo_address_legalidData.evo_city_fias_id',
        undefined,
      );

      if (evo_city_fias_id && objectRegistration === 100000000) {
        CrmService.getCRMEntities<'evo_town', IEvoTown>({
          query: gql`
            query townRegistration($evo_fias_id: String) {
              evo_town(evo_fias_id: $evo_fias_id) {
                evo_fias_id
                evo_townid
              }
            }
          `,
          variables: {
            evo_fias_id: evo_city_fias_id,
          },
        }).then(({ evo_town }) => {
          if (evo_town && !Array.isArray(evo_town)) {
            calculationStore.setValue('townRegistration', evo_town.evo_townid);
            calculationStore.setStatus(
              'selectTownRegistration',
              ElementStatus.Disabled,
            );
          }
        });
      } else {
        calculationStore.setValue('townRegistration', null);
        calculationStore.setStatus(
          'selectTownRegistration',
          ElementStatus.Default,
        );
      }
    },
  }),

  calculationStore => ({
    expression: () => {
      return calculationStore.getValues([
        'regionRegistration',
        'objectRegistration',
      ]);
    },
    effect: () => {
      const objectRegistration =
        calculationStore.getValue('objectRegistration');
      if (objectRegistration === 100000001) {
        calculationStore.setFilter('selectTownRegistration', towns =>
          towns.filter(x => x.evo_businessunit_evolution === true),
        );
      } else {
        calculationStore.setFilter('selectTownRegistration', undefined);
      }
    },
  }),
];

export default gibddReactions;
