/* eslint-disable max-len */
/* eslint-disable no-case-declarations */

import { counting, max, min, shift, sort } from 'radash';
import type RootStore from 'stores/root';
import { areEqual, isSorted } from 'tools/array';
import { SEASONS_PERIODS, SEASONS_PERIOD_NUMBER } from './lib/seasons-constants';

export default function validatePaymentsTable({ $calculation, $tables }: RootStore) {
  switch ($calculation.element('radioGraphType').getValue()) {
    // Дегрессия
    case 100_000_001:
      if (!$calculation.element('selectSeasonType').getValue()) {
        return 'Не выбран тип дегрессии';
      }
      /**
       * в таблице платежей в столбце Соотношение платежей для строк с 2 до "Срок лизинга-1" минимальное значение должно быть равно 3
       */
      {
        const MIN_PAYMENT = 3;
        const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
        const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1);

        if (!targetPayments.every((payment) => payment >= MIN_PAYMENT)) {
          return `Минимальное значение платежа должно быть равно ${MIN_PAYMENT}`;
        }
      }

      /**
       *  при Дегрессии все значения не должны быть равны друг другу + что при Легком старте 2,3 и 4 платежи не должны быть равны 100
       */
      {
        const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
        const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1);

        if (new Set(targetPayments).size === 1) {
          return 'Платежи не должны быть равны друг другу';
        }
      }

      /**
       * Проверка на возрастание
       */
      {
        const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
        const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1);

        for (let i = 2; i < targetPayments.length - 1; i += 1) {
          if (targetPayments[i] > targetPayments[i - 1]) {
            return 'Платежи должны убывать';
          }
        }
      }
      /**
       * Если вид графика = Дегрессия  И значения в "Соотношении платежей" у 2, 3 и 4 платежа отличаются друг от друга не более чем на 10
       * (т.е. берем значения в этих полях, определяем максимальное и минимальное значение и смотрим на их разницу)
       * то не осуществлять Расчет графика и выводить ошибку "Нельзя осуществить расчет - указана очень жетская дегрессия.
       * На 2-4 платежах Соотношение платежа должен отличаться не более чем на 10%",
       * иначе осуществлять расчет
       */
      {
        const targetPayments = $tables.payments.values.slice(1, 4);

        if (max(targetPayments) - min(targetPayments) > 10) {
          return 'Указана очень жесткая дегрессия';
        }
      }

      /**
       * Если вид графика = Дегрессия  И значения в "Соотношении платежей" для строк с 2 До "Срок лизинга-1" как минимум 2 раза по 2 платежа должны между собой быть равны
       * (т.е. берем значения "Соотношения платежей" для строк с 2 до "Срок лизинга-1" и делаем сводную таблицу - если кол-во одинаковых значение больше 2 встречаются 2 и более раза),
       * то осуществлять расчет,
       * иначе не осуществлять Расчет графика и выводить ошибку "Нельзя осуществить расчет - указана очень жетская дегрессия. Не менее чем у 4х платежей "Соотношение платежа" должно не отличаться между самой",
       */
      {
        const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
        const targetPayments = $tables.payments.values.slice(1, leasingPeriod - 1);
        const counts = counting(targetPayments, (v) => v);
        if (Object.values(counts).filter((count) => count > 1).length < 2) {
          return 'Указана очень жесткая дегрессия. Не менее чем у 4х платежей соотношение должно не отличаться между собой';
        }
      }

      break;

    case 100_000_003: {
      const leasingPeriod = $calculation.element('tbxLeasingPeriod').getValue();
      if (leasingPeriod < 14) {
        return 'При сезонном виде графика срок лизинга должен быть больше 14 месяцев';
      }

      const seasonType = $calculation.element('selectSeasonType').getValue();
      if (!seasonType) {
        return 'Не выбран тип сезонности';
      }

      const highSeasonStartOption = $calculation.element('selectHighSeasonStart').getOption();
      if (!highSeasonStartOption) {
        return 'Не выбрано смещение сезонности';
      }

      {
        const seasons = $tables.payments.values.slice(1, SEASONS_PERIOD_NUMBER + 1);
        const shiftNumber = Number.parseInt(highSeasonStartOption.label, 10) - 2;
        const unshiftedSeasons = shift(seasons, -shiftNumber);

        const positions = SEASONS_PERIODS[seasonType];
        const seasonsValues = positions.map((position) => unshiftedSeasons[position]);

        if (isSorted(seasonsValues)) {
          return 'Сезонные платежи должны убывать';
        }
      }

      break;
    }

    // Легкий старт
    case 100_000_004: {
      const targetPayments = $tables.payments.values.slice(1, 4);
      const sortedPayments = sort(targetPayments, (x) => x);
      const areEqualPayments = new Set(targetPayments).size === 1;

      if (!areEqual(targetPayments, sortedPayments) || areEqualPayments) {
        return '2, 3, 4 платежи должны возрастать';
      }

      break;
    }
    default:
      return null;
  }

  return null;
}
