import {
  ElementsNames,
  InteractionElementsNames,
} from 'client/Containers/Calculation/types/elements';
import {
  Table,
  TableNames,
  TableValuesNames,
} from 'client/Containers/Calculation/types/tables';
import { TCalculationProcess } from 'client/stores/CalculationStore/subStores/calculationProcess';
import { TCalculationUrls } from 'client/stores/CalculationStore/subStores/calculationUrls';
import { TELTStore } from 'client/stores/CalculationStore/subStores/eltStore';
import { TFinGAP } from 'client/stores/CalculationStore/subStores/finGAP';
import {
  IBaseOption,
  TOptionizedEntity,
} from 'core/services/CrmService/types/common';
import {
  CRMEntity,
  CRMEntityNames,
} from 'core/services/CrmService/types/entities';
import { ElementStatus } from 'types/elements';
import { TElementFilter } from './filters';
import { TStaticData } from './staticData';
import { ValuesNames } from './values';

export type ElementParam =
  | 'value'
  | 'status'
  | 'options'
  | 'filter'
  | 'validation';

interface ICalculationValues {
  staticData: TStaticData;
  getStaticData: (dataName: CRMEntityNames) => CRMEntity[];
  applyStaticData: (data: TStaticData) => void;

  options: Record<ElementsNames, TOptionizedEntity[]>;
  getOption: (
    elementName: ElementsNames,
    fields?: { [field in keyof (IBaseOption & CRMEntity)]?: any },
  ) => (IBaseOption & CRMEntity) | undefined;
  getOptions: (
    elementName: ElementsNames,
    fields?: { [field in keyof (IBaseOption & CRMEntity)]?: any },
    filtered?: boolean,
  ) => (IBaseOption & CRMEntity)[] | undefined;
  setOptions: (
    elementName: ElementsNames,
    options: TOptionizedEntity[],
  ) => void;
  applyOptions: (
    options: Partial<Record<ElementsNames, TOptionizedEntity[]>>,
  ) => void;

  filters: Record<ElementsNames, TElementFilter>;
  getFilter: (elementName: ElementsNames) => TElementFilter | undefined;
  setFilter: (
    elementName: ElementsNames,
    filter: TElementFilter | undefined,
  ) => void;
  // applyFilters: (filters: TElementFilter[]) => void;

  values: Record<ValuesNames, any>;
  getValue: (sourceValueName: ValuesNames) => any;
  getValues: (valuesNames: ValuesNames[]) => Partial<Record<ValuesNames, any>>;
  setValue: (sourceValueName: ValuesNames, newValue: any) => void;
  setValues: (
    values: Partial<Record<ValuesNames, any>>,
    override?: boolean,
  ) => void;

  statuses: Record<InteractionElementsNames, ElementStatus>;
  getStatus: (elementName: InteractionElementsNames) => ElementStatus;
  setStatus: (
    elementName: InteractionElementsNames,
    status: ElementStatus,
  ) => void;
  setStatuses: (
    statuses: Partial<Record<InteractionElementsNames, ElementStatus>>,
    override?: boolean,
  ) => void;

  validations: Record<ElementsNames, boolean>;
  getValidation: (elementName: ElementsNames) => boolean;
  setValidation: (
    elementName: ElementsNames,
    validation: boolean | undefined,
  ) => void;
}

interface ICalculationTables {
  tables: Record<TableNames, Table>;

  cleanTable: (tableName: TableNames) => void;
  getTableRowValues: (
    tableName: TableNames,
    rowIndex: number | ((rows: Table['rows']) => number),
    paramName: ElementParam,
  ) => Record<TableValuesNames, any>;

  getTableRowValue: (
    tableName: TableNames,
    rowIndex: number | ((rows: Table['rows']) => number),
    propName: TableValuesNames,
    paramName: ElementParam,
  ) => any;

  getTableOptions: (
    tableName: TableNames,
    propName: TableValuesNames,
  ) => TOptionizedEntity[];

  replaceTableRows: (tableName: TableNames) => (rows: Table['rows']) => void;

  setTableRows: (
    tableName: TableNames,
    startIndex: number,
    override?: boolean,
  ) => (rows: Table['rows']) => void;

  setTableRow: (
    tableName: TableNames,
    rowIndex: number | ((rows: Table['rows']) => number),
    override?: boolean,
  ) => (row: Table['rows'][number]) => void;

  setTableColumns: (
    tableName: TableNames,
    override?: boolean,
  ) => ({ options }: { options?: Table['options'] }) => void;
}

interface ICalculationStores {
  stores: {
    calculationProcess: TCalculationProcess;
    calculationUrls: TCalculationUrls;
    ELTStore: TELTStore;
    $finGAP: TFinGAP;
  };
}

export type ICalculationStore = ICalculationValues &
  ICalculationTables &
  ICalculationStores;
