/* eslint-disable object-curly-newline */
import type * as Insurance from 'Components/Calculation/Form/Insurance/InsuranceTable/types';
import * as insuranceTableConfig from 'config/tables/insurance-table';
import { makeAutoObservable } from 'mobx';
import type RootStore from 'stores/root';
import Validation from '../../validation';
import type { ValidationParams } from '../../validation/types';

export interface InsuranceTableData {
  values?: Insurance.RowValues[];
  options?: Record<Insurance.Keys, Insurance.RowOptions>;
  statuses?: Record<Insurance.Keys, Insurance.RowStatuses>;
}

export default class InsuranceTable {
  root: RootStore;
  validation: Validation;
  values: Insurance.RowValues[] = insuranceTableConfig.defaultValues;
  options: Record<Insurance.Keys, Insurance.RowOptions> = insuranceTableConfig.defaultOptions;
  statuses: Record<Insurance.Keys, Insurance.RowStatuses> = insuranceTableConfig.defaultStatuses;

  constructor(rootStore: RootStore) {
    this.validation = new Validation({
      err_key: 'ERR_INSURANCE_TABLE',
      err_title: 'Таблица страхования',
    });

    makeAutoObservable(this);
    this.root = rootStore;
  }

  hydrate = ({
    values: initialValues,
    options: initialOptions,
    statuses: initialStatuses,
  }: InsuranceTableData) => {
    if (initialValues) this.values = initialValues;
    if (initialOptions) this.options = initialOptions;
    if (initialStatuses) this.statuses = initialStatuses;
  };

  validate = ({ invalid, message }: ValidationParams) => {
    if (invalid) {
      this.validation?.addError(message);
    } else {
      this.validation?.removeError(message);
    }
  };

  reset = () => {
    this.values = insuranceTableConfig.defaultValues;
    this.options = insuranceTableConfig.defaultOptions;
    this.statuses = insuranceTableConfig.defaultStatuses;
    this.validation.clearErrors();
  };

  row = <K extends Insurance.Keys>(key: K) => ({
    getValue: <V extends Insurance.Values>(valueName: V) => {
      const rowIndex = this.values.findIndex((x) => x.key === key);

      return this.values[rowIndex][valueName];
    },

    getStatus: (valueName: Insurance.Values) => this.statuses[key][valueName],

    getOptions: (valueName: Insurance.Values) => this.options[key][valueName],

    setValue: <V extends Insurance.Values>(valueName: V, value: Insurance.RowValues[V]) => {
      const rowIndex = this.values.findIndex((x) => x.key === key);

      this.values[rowIndex] = { ...this.values[rowIndex], [valueName]: value };

      return this.row(key);
    },

    block: (valueName: Insurance.Values) => {
      this.statuses[key][valueName] = 'Disabled';

      return this.row(key);
    },

    unblock: (valueName: Insurance.Values) => {
      this.statuses[key][valueName] = 'Default';

      return this.row(key);
    },

    setOptions: <V extends Insurance.Values>(valueName: V, options: Insurance.RowOptions[V]) => {
      this.options[key][valueName] = options;

      return this.row(key);
    },

    resetValue: (valueName: Insurance.Values) => {
      const rowIndex = this.values.findIndex((x) => x.key === key);

      const defaultValue = insuranceTableConfig.defaultValues[rowIndex][valueName];
      this.values[rowIndex] = { ...this.values[rowIndex], [valueName]: defaultValue };

      return this.row(key);
    },

    resetStatus: (valueName: Insurance.Values) => {
      this.statuses[key][valueName] = insuranceTableConfig.defaultStatuses[key][valueName];

      return this.row(key);
    },

    resetOptions: <V extends Insurance.Values>(valueName: V) => {
      this.options[key][valueName] = insuranceTableConfig.defaultOptions[key][valueName];

      return this.row(key);
    },

    reset: (valueName: Insurance.Values) => {
      this.row(key).resetValue(valueName).resetStatus(valueName).resetOptions(valueName);

      return this.row(key);
    },
  });
}
