import { InventoryModel } from '../models/Inventory.model';
import { ReceivableModel } from '../models/Receivable.model';
import { ECollaterals } from '../enums/collaterals.enum';

interface IFormatterOptions {
  fractions?: number;
  nullValue?: string;
}

const defaultFormatterOptions = {
  fractions: 2,
};

export const convertToPercentage = (value: number, total: number) => {
  return ((100 * value) / total).toFixed(2);
};

export const getDigitsFrequencies = (firstDigits: number[]) => {
  const digitCounts = Array(10).fill(0);

  for (const n of firstDigits) {
    digitCounts[n]++;
  }

  return digitCounts;
}

export const uniqueDates = async (borrowerId: string, deep: number, collateral: ECollaterals) => {

  let bbcDates;
  switch (collateral) {
    case ECollaterals.INVENTORY:
      bbcDates = await InventoryModel.find({ borrowerId }, { _id: 1, bbcDate: 1 }).sort([['bbcDate', -1]]);
      break;
    case ECollaterals.RECEIVABLE:
      bbcDates = await ReceivableModel.find({ borrowerId }, { _id: 1, bbcDate: 1 }).sort([['bbcDate', -1]])
      break;
    default:
      throw new Error('Wrong collateral type')
  }
  return [...new Set(bbcDates.map((i) => i.bbcDate.toString()))]
    .map((bbcDate: string) => ({ bbcDate: new Date(bbcDate) }))
    .sort((a, b) => new Date(a.bbcDate).valueOf() - new Date(b.bbcDate).valueOf())
    .slice(-deep);
}

export const round = (num: number) => {
  const m = Number((Math.abs(num) * 100).toPrecision(15));
  return Math.round(m) / 100 * Math.sign(num);
}

export const roundToXDigits = (value: number, digits = 2) => {
  value = value * Math.pow(10, digits);
  value = Math.round(value);
  value = value / Math.pow(10, digits);
  return value;
}

export function numberWithCommas(x: number | string) {
  try {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  } catch (e) {
    return x.toString();
  }
}

export function formatNumbers(value: number | string, formatterOptions?: IFormatterOptions): string {
  try {
    const options = { ...defaultFormatterOptions, ...formatterOptions };
    if (typeof value !== 'number') {
      return value;
    }
    value = Number(value);
    if (value === 0 && options.nullValue) {
      return options.nullValue;
    }
    return numberWithCommas((Math.round(Number(value) * 100) / 100).toFixed(options.fractions));
  } catch (e) {
    return value.toString();
  }
}
