import { IOrchestratorModelConfig } from './config';
import { IModel, models } from './models';

type findMatchFunc = (
  model: IModel,
  key: string,
  value: string | string[]
) => boolean;

const matchWithDot: findMatchFunc = (model, key, value) =>
  typeof value === 'string' && value.split('.').pop() === model[key];

const matchPath: findMatchFunc = (model, key, value) =>
  key === 'path' && typeof value === 'string' && model[key].startsWith(value);

export const findMatchingModel = (
  model: Partial<IModel>,
  config: {
    useDotValues?: boolean;
  } = {
    useDotValues: false
  }
): IModel =>
  Object.keys(model).length > 0
    ? models.links.find((m) =>
        Object.entries(model).every(
          ([key, value]) =>
            value === m[key] ||
            (config.useDotValues && matchWithDot(m, key, value)) ||
            matchPath(m, key, value)
        )
      )
    : null;

const modelMatchOrder = ({
  model,
  value
}: Pick<IOrchestratorModelConfig, 'model' | 'value'>) =>
  [
    { model, term: value },
    { model, modelKey: value },
    {
      model,
      modelKey: value.split('.').pop()
    },
    {
      model,
      term: value.split('.').pop()
    },
    {
      model,
      path: ['hestia_earth', 'models', model, value].join('/')
    },
    !value || value === 'all' ? { model } : null
  ].filter(Boolean) as Partial<IModel>[];

export const findMatchingModelFromConfig = (
  model: Pick<IOrchestratorModelConfig, 'model' | 'value'>
) =>
  modelMatchOrder(model)
    .map(
      (params) =>
        findMatchingModel(params) ||
        findMatchingModel(params, { useDotValues: true })
    )
    ?.filter(Boolean)
    ?.shift();
