/**
 * Metadata singleton and accessor helpers for the libphonenumber polyfill.
 */
import rawMetadata from './metadata.json';
// ---------------------------------------------------------------------------
// Metadata singleton
// ---------------------------------------------------------------------------
export const META = rawMetadata;
// ---------------------------------------------------------------------------
// eslint-disable-next-line spellcheck/spell-checker
// Metadata accessors
// ---------------------------------------------------------------------------
/**
 * Return the calling code string for a given country code.
 *
 * @param {VegaCountryCode} country - the country code to look up
 * @returns {string} the calling code for the given country
 * @example getCountryCallingCode('US') // '1'
 */
export function getCountryCallingCode(country) {
  const entry = META.countries[country];
  if (!entry) {
    throw new Error('Unknown country: ' + country);
  }
  return entry[0];
}
/**
 * Return an array of all supported country codes.
 *
 * @returns {VegaCountryCode[]} an array of supported country codes
 */
export function getCountries() {
  return Object.keys(META.countries);
}
/**
 * Get the list of format rules for a country. Returns undefined if none.
 *
 * @param {VegaCountryCode} country - the country code to retrieve formats for
 * @returns {FormatRule[] | undefined} the format rules or undefined
 */
export function getFormats(country) {
  const entry = META.countries[country];
  if (!entry)
    return undefined;
  const formats = entry[4];
  if (formats && Array.isArray(formats))
    return formats;
  // Country has no own formats — inherit from the primary country
  // sharing the same calling code (e.g., CA/VI inherit from US).
  const callingCode = entry[0];
  const siblings = META.countryCallingCode[callingCode];
  if (siblings) {
    for (const sibling of siblings) {
      if (sibling === country)
        continue;
      const siblingEntry = META.countries[sibling];
      if (siblingEntry) {
        const siblingFormats = siblingEntry[4];
        if (siblingFormats && Array.isArray(siblingFormats))
          return siblingFormats;
      }
    }
  }
  return undefined;
}
// ---------------------------------------------------------------------------
// Country detection
// ---------------------------------------------------------------------------
/**
 * Given digits (without leading +), detect which calling code prefix matches.
 *
 * @param {string} digits - the digit string to detect a calling code from
 * @returns {{ countries: string[] | undefined; callingCode: string | undefined }} the matched countries and calling code
 */
export function detectCallingCode(digits) {
  for (let length = Math.min(3, digits.length); length >= 1; length--) {
    const candidate = digits.substring(0, length);
    const countries = META.countryCallingCode[candidate];
    if (countries && countries.length > 0) {
      return { countries, callingCode: candidate };
    }
  }
  return { countries: undefined, callingCode: undefined };
}
/**
 * Determine the specific country from a set of countries sharing the same
 * calling code, by checking leading digits patterns and validation patterns.
 *
 * Mirrors getCountryByNationalNumber from the original library.
 *
 * @param {string[]} possibleCountries - the candidate country codes
 * @param {string} nationalNumber - the national number to match against
 * @returns {VegaCountryCode | undefined} the matched country or undefined
 */
export function getCountryByNationalNumber(possibleCountries, nationalNumber) {
  // First pass: check countries with leadingDigits (most specific).
  for (const country of possibleCountries) {
    const entry = META.countries[country];
    if (!entry)
      continue;
    const leadingDigits = entry[10];
    if (leadingDigits && typeof leadingDigits === 'string') {
      const prefixMatch = new RegExp('^(?:' + leadingDigits + ')').test(nationalNumber);
      if (nationalNumber && prefixMatch) {
        return country;
      }
    }
  }
  // Second pass: check countries by type patterns (without leadingDigits).
  for (const country of possibleCountries) {
    const entry = META.countries[country];
    if (!entry)
      continue;
    const leadingDigits = entry[10];
    if (leadingDigits && typeof leadingDigits === 'string') {
      // Already handled in first pass.
      continue;
    }
    const types = entry[11];
    if (types && Array.isArray(types)) {
      if (matchesAnyType(nationalNumber, types)) {
        return country;
      }
    }
  }
  return undefined;
}
/**
 * Check if a national number matches any of the type patterns.
 *
 * @param {string} nationalNumber - the national number to test
 * @param {unknown[]} types - the type pattern entries to match against
 * @returns {boolean} whether the national number matches any type pattern
 */
function matchesAnyType(nationalNumber, types) {
  for (const typeEntry of types) {
    if (!typeEntry || typeEntry === 0)
      continue;
    if (Array.isArray(typeEntry)) {
      const pattern = typeEntry[0];
      if (typeof pattern === 'string' && pattern) {
        const isMatch = new RegExp('^(?:' + pattern + ')$').test(nationalNumber);
        if (isMatch) {
          return true;
        }
      }
    }
  }
  return false;
}
