import { resolve } from 'path';
import { existsSync, readFileSync } from 'fs';
import { Carrier } from './metadata/carrier';

interface DataValidationError {
  message?: string;
  duplicateKeys?: string[];
}

const getDuplicateKeys = (dataArray: { key: string }[]): string[] | undefined => {
  let keys: string[] = [];
  let keyContainer = Object.create(null);
  dataArray.forEach((arrayItem) => {
    if (arrayItem['key']) {
      if (keyContainer[arrayItem['key']]) {
        keys.push(arrayItem['key']);
      } else {
        keyContainer[arrayItem['key']] = true;
      }
    }
  });

  return keys.length > 0 ? keys : undefined;
};

const validate = (dataFilePath: string, dataType: string): DataValidationError | undefined => {
  if (existsSync(dataFilePath)) {
    const dataBuffer = readFileSync(dataFilePath);
    const json = JSON.parse(dataBuffer.toString());
    const data = json?.[dataType] || [];

    const duplicates = getDuplicateKeys(data);
    if (duplicates) {
      return {
        message: `${dataType} in ${dataFilePath} contains duplicate keys.`,
        duplicateKeys: duplicates,
      };
    }
  }
};

export const isDataValidationError = (
  errors: DataValidationError[] | undefined,
): errors is DataValidationError[] => errors !== undefined;

export const validateRatingData = (carrier: Carrier): DataValidationError[] | undefined => {
  let errors: DataValidationError[] = [];
  let basePath = carrier.NativeRating?.Path ?? '';

  let error = validate(resolve(basePath, 'zones.json'), 'zones');
  if (error) errors.push(error);

  carrier.NativeRating?.RateCards?.forEach((rateCard) => {
    error = validate(resolve(basePath, rateCard.Id, 'rates.json'), 'rates');
    if (error) errors.push(error);
    error = validate(resolve(basePath, rateCard.Id, 'variables.json'), 'variables');
    if (error) errors.push(error);
  });

  return errors.length > 0 ? errors : undefined;
};
