// 2026-11-10 — Read City + Country out of an audit request's free-text "Location".
// The audit request form has only ONE location field (e.g. "AL QOUZ INDUSTRIAL AREA, DUBAI, UAE",
// "Jeddah, Kingdom of Saudi Arabia", "abu dhabi"). Companies need city + country_id, so this
// recognises known city names / aliases and country names / aliases. Unknown text → null (never guessed).

export interface ParsedLocation {
  city: string | null; // canonical display name, e.g. "Abu Dhabi"
  country: string | null; // canonical country name, matching countries.name (case-insensitive)
}

/** [canonical city, country, ...aliases] — aliases are matched as whole words, case-insensitive */
const CITIES: [string, string, ...string[]][] = [
  // United Arab Emirates
  ['Dubai', 'United Arab Emirates', 'dubai', 'duabi', 'dubia', 'dubay', 'deira', 'bur dubai', 'jebel ali', 'jabel ali', 'al quoz', 'al qouz', 'jafza', 'dubai investment park', 'dxb', 'al qusais', 'qusais', 'al nahda', 'karama', 'al barsha', 'jlt'],
  ['Abu Dhabi', 'United Arab Emirates', 'abu dhabi', 'abudhabi', 'abu dabi', 'musaffah', 'mussafah', 'mussafa', 'mussafah industrial', 'icad', 'khalifa city', 'ruwais', 'auh', 'abu dhabii', 'abu dhbai', 'abudabi', 'abu dhaby'],
  ['Sharjah', 'United Arab Emirates', 'sharjah', 'sharja', 'saif zone', 'shj'],
  ['Ajman', 'United Arab Emirates', 'ajman'],
  ['Umm Al Quwain', 'United Arab Emirates', 'umm al quwain', 'umm al qaiwain', 'umm al quwian', 'uaq', 'umalquwain', 'um al quwain', 'umm al quwain'],
  ['Ras Al Khaimah', 'United Arab Emirates', 'ras al khaimah', 'ras al khaima', 'ras al kaimah', 'rak'],
  ['Fujairah', 'United Arab Emirates', 'fujairah', 'fujaira'],
  ['Al Ain', 'United Arab Emirates', 'al ain'],
  ['Khor Fakkan', 'United Arab Emirates', 'khor fakkan', 'khorfakkan'],
  // Saudi Arabia
  ['Riyadh', 'Saudi Arabia', 'riyadh', 'riyad'],
  ['Jeddah', 'Saudi Arabia', 'jeddah', 'jiddah', 'jedda'],
  ['Dammam', 'Saudi Arabia', 'dammam'],
  ['Al Khobar', 'Saudi Arabia', 'al khobar', 'khobar', 'alkhobar'],
  ['Jubail', 'Saudi Arabia', 'jubail', 'al jubail'],
  ['Makkah', 'Saudi Arabia', 'makkah', 'mecca'],
  ['Madinah', 'Saudi Arabia', 'madinah', 'medina'],
  ['Yanbu', 'Saudi Arabia', 'yanbu'],
  ['Tabuk', 'Saudi Arabia', 'tabuk'],
  // Oman / Qatar / Bahrain
  ['Muscat', 'Oman', 'muscat'],
  ['Sohar', 'Oman', 'sohar'],
  ['Salalah', 'Oman', 'salalah'],
  ['Doha', 'Qatar', 'doha'],
  ['Manama', 'Bahrain', 'manama'],
  // Pakistan
  ['Lahore', 'Pakistan', 'lahore'],
  ['Karachi', 'Pakistan', 'karachi'],
  ['Islamabad', 'Pakistan', 'islamabad'],
  ['Rawalpindi', 'Pakistan', 'rawalpindi'],
  ['Peshawar', 'Pakistan', 'peshawar', 'peshwar'],
  ['Multan', 'Pakistan', 'multan'],
  ['Faisalabad', 'Pakistan', 'faisalabad'],
  ['Quetta', 'Pakistan', 'quetta'],
  ['Sialkot', 'Pakistan', 'sialkot'],
  ['Gujranwala', 'Pakistan', 'gujranwala'],
  // India
  ['Mumbai', 'India', 'mumbai', 'bombay'],
  ['New Delhi', 'India', 'new delhi', 'delhi'],
  ['Bengaluru', 'India', 'bengaluru', 'bangalore'],
  ['Chennai', 'India', 'chennai'],
  ['Hyderabad', 'India', 'hyderabad'],
  ['Kolkata', 'India', 'kolkata'],
  ['Pune', 'India', 'pune'],
  ['Ahmedabad', 'India', 'ahmedabad'],
  ['Kochi', 'India', 'kochi', 'cochin'],
  // others in the countries table
  ['Cairo', 'Egypt', 'cairo', 'new cairo'],
  ['Alexandria', 'Egypt', 'alexandria'],
  ['Hanoi', 'Vietnam', 'hanoi', 'ha noi', 'hà nội'],
  ['Ho Chi Minh City', 'Vietnam', 'ho chi minh', 'saigon'],
  ['Hai Phong', 'Vietnam', 'hai phong', 'hải phòng'],
  ['Istanbul', 'Turkey', 'istanbul'],
  ['Ankara', 'Turkey', 'ankara'],
  ['Baghdad', 'IRAQ', 'baghdad'],
  ['Erbil', 'IRAQ', 'erbil'],
  ['Basra', 'IRAQ', 'basra', 'basrah'],
  ['Tehran', 'IRAN', 'tehran'],
  ['Johannesburg', 'South Africa', 'johannesburg', 'johannesberg'],
  ['Cape Town', 'South Africa', 'cape town'],
  ['Pretoria', 'South Africa', 'pretoria'],
  ['Kabul', 'Afghanistan', 'kabul'],
];

/** [canonical country (= countries.name), ...aliases] */
const COUNTRIES: [string, ...string[]][] = [
  ['United Arab Emirates', 'united arab emirates', 'uae', 'u a e', 'emirates'],
  ['Saudi Arabia', 'saudi arabia', 'kingdom of saudi arabia', 'ksa', 'k s a', 'saudi'],
  ['Oman', 'oman', 'sultanate of oman'],
  ['Qatar', 'qatar'],
  ['Bahrain', 'bahrain', 'kingdom of bahrain'],
  ['Pakistan', 'pakistan'],
  ['India', 'india'],
  ['Egypt', 'egypt'],
  ['Vietnam', 'vietnam', 'viet nam'],
  ['Turkey', 'turkey', 'turkiye', 'türkiye'],
  ['IRAQ', 'iraq'],
  ['IRAN', 'iran'],
  ['South Africa', 'south africa'],
  ['USA', 'usa', 'u s a', 'united states', 'united states of america'],
  ['Afghanistan', 'afghanistan'],
  ['Turkmenistan', 'turkmenistan'],
];

const norm = (s: string) =>
  ` ${String(s || '')
    .toLowerCase()
    .replace(/[^\p{L}\p{N}]+/gu, ' ')
    .replace(/\s+/g, ' ')
    .trim()} `;

/** position of the LAST whole-word match of any alias (-1 = none); longer aliases win ties */
function lastMatch(hay: string, aliases: string[]): number {
  let best = -1;
  for (const a of aliases) {
    const needle = norm(a);
    const i = hay.lastIndexOf(needle);
    if (i > best) best = i;
  }
  return best;
}

export function parseLocation(location: string | null | undefined): ParsedLocation {
  const hay = norm(location || '');
  if (hay.trim() === '') return { city: null, country: null };

  // city: the right-most known city in the text (addresses go street → area → city → country)
  let city: { name: string; country: string; at: number } | null = null;
  for (const [name, country, ...aliases] of CITIES) {
    const at = lastMatch(hay, aliases);
    if (at >= 0 && (!city || at > city.at)) city = { name, country, at };
  }

  // country: an explicit country name in the text wins; otherwise the city's country
  let country: { name: string; at: number } | null = null;
  for (const [name, ...aliases] of COUNTRIES) {
    const at = lastMatch(hay, aliases);
    if (at >= 0 && (!country || at > country.at)) country = { name, at };
  }

  // city and country disagree (e.g. "SAUDI and ABU DHABI") → the one written last wins
  if (city && country && country.name !== city.country && city.at > country.at) {
    return { city: city.name, country: city.country };
  }
  return {
    city: city?.name ?? null,
    country: country?.name ?? city?.country ?? null,
  };
}
