/* eslint-disable @typescript-eslint/naming-convention */
import { gql } from '@apollo/client';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import type * as CRMTypes from 'gql/crm.types';
import { reaction } from 'mobx';
import type { ReactionsContext } from 'process/types';
import { makeDisposable } from 'tools/mobx';
import * as createReactions from '../lib/create-reactions';
import * as fillAgentsFromLead from '../lib/fill-agents-from-lead';

dayjs.extend(utc);

export function fillReactions({ store, apolloClient }: ReactionsContext) {
  const { $calculation, $process } = store;

  /**
   * Заполняем агентов из Интереса
   */
  makeDisposable(
    () =>
      reaction(
        () => $calculation.element('selectLead').getValue(),
        (leadid) => {
          fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid);
          fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid);
          fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid);
          fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
        }
      ),
    () => $process.has('LoadKP')
  );

  /**
   * IndAgent
   */
  // Заполняем selectIndAgentRewardCondition
  createReactions.fillAgentRewardReaction(store, apolloClient, {
    agentField: 'selectIndAgent',
    rewardConditionField: 'selectIndAgentRewardCondition',
  });

  // Заполняем tbxIndAgentRewardSumm
  createReactions.fillAgentRewardSummReaction(store, apolloClient, {
    rewardConditionField: 'selectIndAgentRewardCondition',
    rewardSummField: 'tbxIndAgentRewardSumm',
  });

  /**
   * CalcDoubleAgent
   */
  // Заполняем selectCalcDoubleAgentRewardCondition
  createReactions.fillAgentRewardReaction(store, apolloClient, {
    agentField: 'selectCalcDoubleAgent',
    rewardConditionField: 'selectCalcDoubleAgentRewardCondition',
  });

  // Заполняем tbxCalcDoubleAgentRewardSumm
  createReactions.fillAgentRewardSummReaction(store, apolloClient, {
    rewardConditionField: 'selectCalcDoubleAgentRewardCondition',
    rewardSummField: 'tbxCalcDoubleAgentRewardSumm',
  });

  /**
   * CalcBroker
   */
  // Заполняем selectCalcBrokerRewardCondition
  createReactions.fillAgentRewardReaction(store, apolloClient, {
    agentField: 'selectCalcBroker',
    rewardConditionField: 'selectCalcBrokerRewardCondition',
  });

  // Заполняем tbxCalcBrokerRewardSum
  createReactions.fillAgentRewardSummReaction(store, apolloClient, {
    rewardConditionField: 'selectCalcBrokerRewardCondition',
    rewardSummField: 'tbxCalcBrokerRewardSum',
  });

  /**
   * CalcFinDepartment
   */
  // Заполняем selectFinDepartmentRewardCondtion
  createReactions.fillAgentRewardReaction(store, apolloClient, {
    agentField: 'selectCalcFinDepartment',
    rewardConditionField: 'selectFinDepartmentRewardCondtion',
  });

  // Заполняем tbxCalcBrokerRewardSum
  createReactions.fillAgentRewardSummReaction(store, apolloClient, {
    rewardConditionField: 'selectFinDepartmentRewardCondtion',
    rewardSummField: 'tbxFinDepartmentRewardSumm',
  });
}

export function commonReactions({ store, apolloClient }: ReactionsContext) {
  const { $calculation } = store;

  const QUERY_GET_REWARD_WITHOUT_OTHER_AGENT = gql`
    query GetRewardWithoutOtherAgent($conditionId: Uuid!) {
      evo_reward_condition(evo_reward_conditionid: $conditionId) {
        evo_agency_agreementidData {
          evo_reward_without_other_agent
        }
      }
    }
  `;

  /**
   * Добавить реакцию на изменение списка в поле selectDealerRewardCondition :
        Если в списке selectDealerRewardCondition есть запись,
        у которой evo_reward_condition.evo_agency_agreementid.
        Выплата без других агентов (evo_reward_without_other_agent) = True,
        то сбрасывают значение и закрываются для выбора поля:

        selectDealerBroker
        selectIndAgent
        selectCalcDoubleAgent
        selectCalcBroker
        selectFinDepartment
   */

  reaction(
    () => $calculation.element('selectDealerRewardCondition').getValue(),
    async (rewardConditionId) => {
      function fillAgents() {
        const leadid = $calculation.element('selectLead').getValue();
        fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid);
        fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid);
        fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid);
        fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
      }

      if (!rewardConditionId) {
        fillAgents();

        return;
      }

      const {
        data: { evo_reward_condition },
      } = await apolloClient.query<
        CRMTypes.GetRewardWithoutOtherAgentQuery,
        CRMTypes.GetRewardWithoutOtherAgentQueryVariables
      >({
        query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT,
        variables: {
          conditionId: rewardConditionId,
        },
      });

      if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) {
        $calculation.element('selectDealerBroker').reset();
        $calculation.element('selectIndAgent').reset();
        $calculation.element('selectCalcDoubleAgent').reset();
        $calculation.element('selectCalcBroker').reset();
        $calculation.element('selectCalcFinDepartment').reset();
      } else {
        fillAgents();
      }
    }
  );

  /**
   * Добавить реакцию на изменение списка в поле selectDealerBrokerRewardCondition :

    Если в списке selectDealerBrokerRewardCondition есть запись,
    у которой evo_reward_condition.evo_agency_agreementid.
    Выплата без других агентов (evo_reward_without_other_agent) = True,
    то сбрасывают значение и закрываются для выбора поля:

    selectDealerPerson (не обнуляем)
    selectIndAgent
    selectCalcDoubleAgent
    selectCalcBroker
    selectFinDepartment
    иначе

    selectDealerPerson открываем для редактирования
    selectIndAgent заполняется значением из Интереса
    selectCalcDoubleAgent заполняется значением из Интереса
    selectCalcBrokerRewardCondition заполняется значением из Интереса
    selectFinDepartmentRewardCondtion заполняется значением из Интереса
   */
  reaction(
    () => $calculation.element('selectDealerBrokerRewardCondition').getValue(),
    async (rewardConditionId) => {
      function fillAgents() {
        const leadid = $calculation.element('selectLead').getValue();
        fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid);
        fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid);
        fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid);
        fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
      }

      if (!rewardConditionId) {
        fillAgents();

        return;
      }

      const {
        data: { evo_reward_condition },
      } = await apolloClient.query<
        CRMTypes.GetRewardWithoutOtherAgentQuery,
        CRMTypes.GetRewardWithoutOtherAgentQueryVariables
      >({
        query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT,
        variables: {
          conditionId: rewardConditionId,
        },
      });

      if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) {
        $calculation.element('selectDealerPerson').block();
        $calculation.element('selectIndAgent').reset();
        $calculation.element('selectCalcDoubleAgent').reset();
        $calculation.element('selectCalcBroker').reset();
        $calculation.element('selectCalcFinDepartment').reset();
      } else {
        $calculation.element('selectDealerPerson').unblock();
        fillAgents();
      }
    }
  );

  /**
   * Добавить реакцию на изменение списка в поле selectIndAgentRewardCondition :

    Если в списке selectIndAgentRewardCondition есть запись,
    у которой evo_reward_condition.evo_agency_agreementid.
    Выплата без других агентов (evo_reward_without_other_agent) = True,
    то сбрасывают значение и закрываются для выбора поля:

    selectDealerPerson (не обнуляем)
    selectDealerBroker
    selectCalcDoubleAgent
    selectCalcBroker
    selectFinDepartment
    иначе

    selectDealerPerson открываем для редактирования
    selectDealerBroker открываем для редактирования
    selectCalcDoubleAgent заполняется значением из Интереса
    selectCalcBroker заполняется значением из Интереса
    selectCalcFinDepartment заполняется значением из Интереса
   */

  reaction(
    () => $calculation.element('selectIndAgentRewardCondition').getValue(),
    async (rewardConditionId) => {
      function fillAgents() {
        const leadid = $calculation.element('selectLead').getValue();
        fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid);
        fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid);
        fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
      }

      if (!rewardConditionId) {
        fillAgents();

        return;
      }

      const {
        data: { evo_reward_condition },
      } = await apolloClient.query<
        CRMTypes.GetRewardWithoutOtherAgentQuery,
        CRMTypes.GetRewardWithoutOtherAgentQueryVariables
      >({
        query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT,
        variables: {
          conditionId: rewardConditionId,
        },
      });

      if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) {
        $calculation.element('selectDealerPerson').block();
        $calculation.element('selectDealerBroker').reset();
        $calculation.element('selectCalcDoubleAgent').reset();
        $calculation.element('selectCalcBroker').reset();
        $calculation.element('selectCalcFinDepartment').reset();
      } else {
        $calculation.element('selectDealerPerson').unblock();
        fillAgents();
      }
    }
  );

  /**
   * Добавить реакцию на изменение списка в поле selectCalcDoubleAgentRewardCondition :

    Если в списке selectCalcDoubleAgentRewardCondition есть запись,
    у которой evo_reward_condition.evo_agency_agreementid.
    Выплата без других агентов (evo_reward_without_other_agent) = True,
    то сбрасывают значение и закрываются для выбора поля:

    selectDealerPerson (не обнуляем)
    selectDealerBroker
    selectIndAgent
    selectCalcBroker
    selectCalcFinDepartment
    иначе

    selectDealerPerson открываем для редактирования
    selectDealerBroker открываем для редактирования
    selectIndAgent заполняется значением из Интереса
    selectCalcBroker заполняется значением из Интереса
    selectCalcFinDepartment заполняется значением из Интереса
   */

  reaction(
    () => $calculation.element('selectCalcDoubleAgentRewardCondition').getValue(),
    async (rewardConditionId) => {
      function fillAgents() {
        const leadid = $calculation.element('selectLead').getValue();
        fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid);
        fillAgentsFromLead.fillCalcBroker(store, apolloClient, leadid);
        fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
      }

      if (!rewardConditionId) {
        fillAgents();

        return;
      }

      const {
        data: { evo_reward_condition },
      } = await apolloClient.query<
        CRMTypes.GetRewardWithoutOtherAgentQuery,
        CRMTypes.GetRewardWithoutOtherAgentQueryVariables
      >({
        query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT,
        variables: {
          conditionId: rewardConditionId,
        },
      });

      if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) {
        $calculation.element('selectDealerPerson').block();
        $calculation.element('selectDealerBroker').reset();
        $calculation.element('selectIndAgent').reset();
        $calculation.element('selectCalcBroker').reset();
        $calculation.element('selectCalcFinDepartment').reset();
      } else {
        $calculation.element('selectDealerPerson').unblock();
        $calculation.element('selectDealerBroker').unblock();
        fillAgents();
      }
    }
  );

  /**
   * @description
   * Добавить реакцию на изменение списка в поле selectCalcBrokerRewardCondition:

    Если в списке selectCalcBrokerRewardCondition есть запись,
    у которой evo_reward_condition.evo_agency_agreementid.
    Выплата без других агентов (evo_reward_without_other_agent) = True,
    то сбрасывают значение и закрываются для выбора поля:

    selectDealerPerson (не обнуляем)
    selectDealerBroker
    selectIndAgent
    selectCalcDoubleAgent
    selectCalcFinDepartment
    иначе

    selectDealerPerson открываем для редактирования
    selectDealerBroker открываем для редактирования
    selectIndAgent заполняется значением из Интереса
    selectCalcDoubleAgent заполняется значением из Интереса
    selectCalcFinDepartment заполняется значением из Интереса
   */
  reaction(
    () => $calculation.element('selectCalcBrokerRewardCondition').getValue(),
    async (rewardConditionId) => {
      function fillAgents() {
        const leadid = $calculation.element('selectLead').getValue();
        fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid);
        fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid);
        fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
      }

      if (!rewardConditionId) {
        fillAgents();

        return;
      }

      const {
        data: { evo_reward_condition },
      } = await apolloClient.query<
        CRMTypes.GetRewardWithoutOtherAgentQuery,
        CRMTypes.GetRewardWithoutOtherAgentQueryVariables
      >({
        query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT,
        variables: {
          conditionId: rewardConditionId,
        },
      });

      if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) {
        $calculation.element('selectDealerPerson').block();
        $calculation.element('selectDealerBroker').reset();
        $calculation.element('selectIndAgent').reset();
        $calculation.element('selectCalcDoubleAgent').reset();
        $calculation.element('selectCalcFinDepartment').reset();
      } else {
        $calculation.element('selectDealerPerson').unblock();
        $calculation.element('selectDealerBroker').unblock();
        fillAgents();
      }
    }
  );

  /**
   * Добавить реакцию на изменение списка в поле selectFinDepartmentRewardCondtion:

    Если в списке selectFinDepartmentRewardCondtion есть запись,
    у которой evo_reward_condition.evo_agency_agreementid.
    Выплата без других агентов (evo_reward_without_other_agent) = True,
    то сбрасывают значение и закрываются для выбора поля:

    selectDealerPerson (не обнуляем)
    selectDealerBroker
    selectIndAgent
    selectCalcDoubleAgent
    selectCalcBroker
    иначе

    selectDealerPerson открываем для редактирования
    selectDealerBroker открываем для редактирования
    selectIndAgent заполняется значением из Интереса
    selectCalcDoubleAgent заполняется значением из Интереса
    selectCalcBroker заполняется значением из Интереса
   */

  reaction(
    () => $calculation.element('selectFinDepartmentRewardCondtion').getValue(),
    async (rewardConditionId) => {
      function fillAgents() {
        const leadid = $calculation.element('selectLead').getValue();
        fillAgentsFromLead.fillIndAgent(store, apolloClient, leadid);
        fillAgentsFromLead.fillCalcDoubleAgent(store, apolloClient, leadid);
        fillAgentsFromLead.fillFinDepartment(store, apolloClient, leadid);
      }

      if (!rewardConditionId) {
        fillAgents();

        return;
      }

      const {
        data: { evo_reward_condition },
      } = await apolloClient.query<
        CRMTypes.GetRewardWithoutOtherAgentQuery,
        CRMTypes.GetRewardWithoutOtherAgentQueryVariables
      >({
        query: QUERY_GET_REWARD_WITHOUT_OTHER_AGENT,
        variables: {
          conditionId: rewardConditionId,
        },
      });

      if (evo_reward_condition?.evo_agency_agreementidData?.evo_reward_without_other_agent) {
        $calculation.element('selectDealerPerson').block();
        $calculation.element('selectDealerBroker').reset();
        $calculation.element('selectIndAgent').reset();
        $calculation.element('selectCalcDoubleAgent').reset();
        $calculation.element('selectCalcBroker').reset();
      } else {
        $calculation.element('selectDealerPerson').unblock();
        $calculation.element('selectDealerBroker').unblock();
        fillAgents();
      }
    }
  );
}

export function validationReactions({ store, apolloClient }: ReactionsContext) {
  createReactions.validateAgentRewardSumm(store, apolloClient, {
    rewardConditionField: 'selectIndAgentRewardCondition',
    rewardSummField: 'tbxIndAgentRewardSumm',
  });

  createReactions.validateAgentRewardSumm(store, apolloClient, {
    rewardConditionField: 'selectCalcDoubleAgentRewardCondition',
    rewardSummField: 'tbxCalcDoubleAgentRewardSumm',
  });

  createReactions.validateAgentRewardSumm(store, apolloClient, {
    rewardConditionField: 'selectCalcBrokerRewardCondition',
    rewardSummField: 'tbxCalcBrokerRewardSum',
  });

  createReactions.validateAgentRewardSumm(store, apolloClient, {
    rewardConditionField: 'selectFinDepartmentRewardCondtion',
    rewardSummField: 'tbxFinDepartmentRewardSumm',
  });
}
