import { PARSE_ERROR_NOT_A_NUMBER, PARSE_ERROR_INVALID_COUNTRY } from './types';
import { META, getCountryCallingCode, detectCallingCode, getCountryByNationalNumber } from './metadata';
import { PhoneNumber } from './phone-number';
// ---------------------------------------------------------------------------
// parseIncompletePhoneNumber
// ---------------------------------------------------------------------------
/**
 * Strip everything except digits and a leading +.
 *
 * Mirrors the behavior of libphonenumber-js/core parseIncompletePhoneNumber.
 *
 * @param {string} text - The raw phone number input to sanitize.
 * @returns {string} The sanitized string containing only digits and an optional leading +.
 * @example parseIncompletePhoneNumber('(302) 333-4444')    // '3023334444'
 * @example parseIncompletePhoneNumber('+1 (302) 333-4444') // '+13023334444'
 */
export function parseIncompletePhoneNumber(text) {
  let result = '';
  for (let i = 0; i < text.length; i++) {
    const char = text[i];
    if (char === '+' && result.length === 0) {
      result += '+';
    }
    else if (char >= '0' && char <= '9') {
      result += char;
    }
  }
  return result;
}
// ---------------------------------------------------------------------------
// parsePhoneNumber
// ---------------------------------------------------------------------------
/**
 * Parse a phone number string into a PhoneNumber instance.
 *
 * @param {string} text - The raw phone number string to parse.
 * @param {VegaCountryCode | ParsePhoneNumberOptions} [optionsOrCountry] - A default country code or parsing options.
 * @returns {PhoneNumber} The parsed PhoneNumber instance.
 * @throws {Error} if the input cannot be parsed.
 */
export function parsePhoneNumber(text, optionsOrCountry) {
  var _a;
  const options = typeof optionsOrCountry === 'string' ? { defaultCountry: optionsOrCountry } : optionsOrCountry !== null && optionsOrCountry !== void 0 ? optionsOrCountry : {};
  const { defaultCountry, extract = true } = options;
  const cleaned = parseIncompletePhoneNumber(text);
  if (!cleaned || cleaned === '+') {
    throw new Error(PARSE_ERROR_NOT_A_NUMBER);
  }
  if (!extract) {
    const stripped = text.replace(/[\s\-().+]/g, '');
    if (!/^\d*$/.test(stripped)) {
      throw new Error(PARSE_ERROR_NOT_A_NUMBER);
    }
  }
  let callingCode = '';
  let nationalNumber;
  let country;
  if (cleaned.startsWith('+')) {
    const digits = cleaned.substring(1);
    const detected = detectCallingCode(digits);
    callingCode = (_a = detected.callingCode) !== null && _a !== void 0 ? _a : '';
    if (!callingCode) {
      throw new Error(PARSE_ERROR_INVALID_COUNTRY);
    }
    nationalNumber = digits.substring(callingCode.length);
    // For NANPA (calling code '1'), strip the trunk prefix '1' if present.
    // E.g. '+113405100000' → nationalNumber '3405100000' so VI can be detected.
    if (callingCode === '1' && nationalNumber.length === 11 && nationalNumber.startsWith('1')) {
      nationalNumber = nationalNumber.substring(1);
    }
    const possibleCountries = detected.countries;
    if (possibleCountries && possibleCountries.length === 1) {
      country = possibleCountries[0];
    }
    else if (possibleCountries && possibleCountries.length > 1) {
      country = getCountryByNationalNumber(possibleCountries, nationalNumber);
    }
  }
  else {
    if (!defaultCountry) {
      throw new Error(PARSE_ERROR_INVALID_COUNTRY);
    }
    callingCode = getCountryCallingCode(defaultCountry);
    nationalNumber = cleaned;
    // For NANPA countries (calling code '1'), the trunk prefix '1' may
    // need to be stripped. E.g. '13405100000' → '3405100000' so that
    // VI (leadingDigits 340) can be detected.
    if (callingCode === '1' && nationalNumber.length === 11 && nationalNumber.startsWith('1')) {
      nationalNumber = nationalNumber.substring(1);
    }
    // For countries sharing a calling code (e.g., NANPA), check if the
    // national number actually belongs to a different country in the group.
    const siblings = META.countryCallingCode[callingCode];
    if (siblings && siblings.length > 1) {
      const detected = getCountryByNationalNumber(siblings, nationalNumber);
      country = detected !== null && detected !== void 0 ? detected : defaultCountry;
    }
    else {
      country = defaultCountry;
    }
  }
  // Extract the national number by stripping the national prefix, if applicable.
  // Mirrors extractNationalNumber from the original library:
  //  1. Match nationalPrefixForParsing against the beginning of nationalNumber.
  //  2. If the original number already matches the validation pattern, keep it.
  //  3. Otherwise, if the stripped version matches the validation pattern, use it.
  if (country) {
    const entry = META.countries[country];
    if (entry) {
      const prefixPattern = entry[7];
      if (prefixPattern && typeof prefixPattern === 'string') {
        const prefixMatch = nationalNumber.match(new RegExp('^(?:' + prefixPattern + ')'));
        if (prefixMatch && prefixMatch[0].length > 0) {
          const afterPrefix = nationalNumber.substring(prefixMatch[0].length);
          const validPattern = entry[2];
          const validRegex = new RegExp('^(?:' + validPattern + ')$');
          const originalMatches = validRegex.test(nationalNumber);
          const strippedMatches = afterPrefix.length > 0 && validRegex.test(afterPrefix);
          if (!originalMatches && strippedMatches) {
            nationalNumber = afterPrefix;
          }
        }
      }
    }
  }
  return new PhoneNumber(callingCode, nationalNumber, country);
}
