import { allowedType, IOrchestratorModelConfig, loadConfig } from './config';
import { findMatchingModelFromConfig } from './utils';

// models not included in the links
const skipModels = ['emissions.deleted', 'transformations'];

const isHestiaResidueCyclicModel = ({
  model,
  value
}: IOrchestratorModelConfig) =>
  model === 'hestia' && value?.startsWith('residue');

const isOrganicCarbonCyclicModel = ({
  model,
  value
}: IOrchestratorModelConfig) =>
  model === 'hestia' && value?.startsWith('organicCarbonPer');

const includeModel = (model: IOrchestratorModelConfig) =>
  [
    !skipModels.includes(model.model),
    // cyclic dependencies
    !isHestiaResidueCyclicModel(model),
    !isOrganicCarbonCyclicModel(model)
  ].every(Boolean);

// dependencies that cannot be validated
const skipDependencies = [
  // completeness gap-fills after other models run
  'completeness'
];

const matchDependencies =
  (models: IOrchestratorModelConfig[]) => (model: IOrchestratorModelConfig) => {
    const { dependencies } = findMatchingModelFromConfig(model);
    const previousModels = models.slice(0, models.indexOf(model));
    const existing =
      dependencies?.filter((value) =>
        previousModels.some(
          (config) => config.value?.split('.').pop() === value
        )
      ) ?? [];
    return {
      model,
      existing,
      missing:
        dependencies
          // skip dependencies that dont exist at all
          ?.filter((value) => models.some((config) => config.value === value))
          ?.filter(
            (v) =>
              !existing.includes(v) &&
              !skipDependencies.includes(v) &&
              v !== model.value
          ) ?? []
    };
  };

export const validateConfig = (nodeType: allowedType) => {
  const config = loadConfig(nodeType);
  // flatten all models to process one by one, starting with the last one
  const models = config.models.flat();

  const results = models.filter(includeModel).map(matchDependencies(models));

  return results.filter((r) => r.missing.length > 0);
};
