export type SyrianCity = {
  id: string;
  name: string;
  country: string;
  region: string;
  latitude: number;
  longitude: number;
};

type CityRecord = SyrianCity & { aliases: string[] };

const cities: CityRecord[] = [
  { id: "sy-damascus", name: "دمشق", country: "سوريا", region: "محافظة دمشق", latitude: 33.5138, longitude: 36.2765, aliases: ["الشام", "damascus", "dimashq"] },
  { id: "sy-aleppo", name: "حلب", country: "سوريا", region: "محافظة حلب", latitude: 36.2021, longitude: 37.1343, aliases: ["aleppo", "halab"] },
  { id: "sy-homs", name: "حمص", country: "سوريا", region: "محافظة حمص", latitude: 34.7324, longitude: 36.7137, aliases: ["homs", "hims"] },
  { id: "sy-hama", name: "حماة", country: "سوريا", region: "محافظة حماة", latitude: 35.1318, longitude: 36.7578, aliases: ["حماه", "hama", "hamah"] },
  { id: "sy-latakia", name: "اللاذقية", country: "سوريا", region: "محافظة اللاذقية", latitude: 35.5317, longitude: 35.7901, aliases: ["لاذقية", "اللادقية", "اللاذقيه", "latakia", "lattakia", "laodicea"] },
  { id: "sy-tartus", name: "طرطوس", country: "سوريا", region: "محافظة طرطوس", latitude: 34.889, longitude: 35.8866, aliases: ["tartus", "tartous"] },
  { id: "sy-idlib", name: "إدلب", country: "سوريا", region: "محافظة إدلب", latitude: 35.9306, longitude: 36.6339, aliases: ["ادلب", "idlib"] },
  { id: "sy-raqqa", name: "الرقة", country: "سوريا", region: "محافظة الرقة", latitude: 35.9506, longitude: 39.0095, aliases: ["رقة", "الرقه", "raqqa", "rakka"] },
  { id: "sy-deir-ez-zor", name: "دير الزور", country: "سوريا", region: "محافظة دير الزور", latitude: 35.3359, longitude: 40.1408, aliases: ["ديرالزور", "دير زور", "deir ez zor", "deir al zor"] },
  { id: "sy-hasakah", name: "الحسكة", country: "سوريا", region: "محافظة الحسكة", latitude: 36.5024, longitude: 40.7477, aliases: ["حسكة", "الحسكه", "hasakah", "hassakeh"] },
  { id: "sy-daraa", name: "درعا", country: "سوريا", region: "محافظة درعا", latitude: 32.6189, longitude: 36.1021, aliases: ["درعة", "daraa", "dara"] },
  { id: "sy-suwayda", name: "السويداء", country: "سوريا", region: "محافظة السويداء", latitude: 32.709, longitude: 36.5695, aliases: ["سويداء", "sweida", "as suwayda"] },
  { id: "sy-quneitra", name: "القنيطرة", country: "سوريا", region: "محافظة القنيطرة", latitude: 33.1259, longitude: 35.8246, aliases: ["قنيطرة", "القنيطره", "quneitra", "kunaitra"] },
  { id: "sy-rif-dimashq", name: "ريف دمشق", country: "سوريا", region: "محافظة ريف دمشق", latitude: 33.5167, longitude: 36.9541, aliases: ["ريف الشام", "damascus countryside"] },
  { id: "sy-qamishli", name: "القامشلي", country: "سوريا", region: "محافظة الحسكة", latitude: 37.0522, longitude: 41.2314, aliases: ["قامشلي", "qamishli", "kamishly"] },
  { id: "sy-manbij", name: "منبج", country: "سوريا", region: "محافظة حلب", latitude: 36.5282, longitude: 37.9544, aliases: ["manbij", "membij"] },
  { id: "sy-afrin", name: "عفرين", country: "سوريا", region: "محافظة حلب", latitude: 36.5119, longitude: 36.8695, aliases: ["afrin"] },
  { id: "sy-al-bab", name: "الباب", country: "سوريا", region: "محافظة حلب", latitude: 36.3705, longitude: 37.5157, aliases: ["باب", "al bab"] },
  { id: "sy-azaz", name: "أعزاز", country: "سوريا", region: "محافظة حلب", latitude: 36.5866, longitude: 37.0463, aliases: ["اعزاز", "azaz"] },
  { id: "sy-salamiyah", name: "السلمية", country: "سوريا", region: "محافظة حماة", latitude: 35.0113, longitude: 37.0532, aliases: ["سلمية", "السلميه", "salamiyah", "salamieh"] },
  { id: "sy-palmyra", name: "تدمر", country: "سوريا", region: "محافظة حمص", latitude: 34.554, longitude: 38.2667, aliases: ["palmyra", "tadmur"] },
  { id: "sy-baniyas", name: "بانياس", country: "سوريا", region: "محافظة طرطوس", latitude: 35.1819, longitude: 35.9487, aliases: ["بانياس الساحل", "baniyas", "banias"] },
  { id: "sy-jableh", name: "جبلة", country: "سوريا", region: "محافظة اللاذقية", latitude: 35.3621, longitude: 35.9276, aliases: ["جبله", "jableh", "jablah"] },
  { id: "sy-safita", name: "صافيتا", country: "سوريا", region: "محافظة طرطوس", latitude: 34.8208, longitude: 36.1177, aliases: ["safita"] },
  { id: "sy-douma", name: "دوما", country: "سوريا", region: "محافظة ريف دمشق", latitude: 33.5718, longitude: 36.4027, aliases: ["douma", "duma"] },
  { id: "sy-darayya", name: "داريا", country: "سوريا", region: "محافظة ريف دمشق", latitude: 33.4584, longitude: 36.2326, aliases: ["darayya", "daraya"] },
  { id: "sy-zabadani", name: "الزبداني", country: "سوريا", region: "محافظة ريف دمشق", latitude: 33.7249, longitude: 36.1005, aliases: ["زبداني", "zabadani"] },
  { id: "sy-bosra", name: "بصرى الشام", country: "سوريا", region: "محافظة درعا", latitude: 32.5186, longitude: 36.4817, aliases: ["بصرى", "bosra", "busra"] },
  { id: "sy-masyaf", name: "مصياف", country: "سوريا", region: "محافظة حماة", latitude: 35.0653, longitude: 36.3428, aliases: ["masyaf"] },
  { id: "sy-maarrat", name: "معرة النعمان", country: "سوريا", region: "محافظة إدلب", latitude: 35.6475, longitude: 36.6769, aliases: ["المعرة", "معره النعمان", "maarrat al numan"] },
];

export function normalizeCitySearch(value: string) {
  return value
    .normalize("NFKD")
    .toLocaleLowerCase("ar")
    .replace(/[\u064B-\u065F\u0670\u06D6-\u06ED]/g, "")
    .replace(/[أإآٱ]/g, "ا")
    .replace(/ى/g, "ي")
    .replace(/ة/g, "ه")
    .replace(/ؤ/g, "و")
    .replace(/ئ/g, "ي")
    .replace(/[^\p{L}\p{N}]+/gu, " ")
    .trim()
    .replace(/\s+/g, " ");
}

function editDistance(left: string, right: string) {
  const previous = Array.from({ length: right.length + 1 }, (_, index) => index);
  for (let leftIndex = 1; leftIndex <= left.length; leftIndex += 1) {
    const current = [leftIndex];
    for (let rightIndex = 1; rightIndex <= right.length; rightIndex += 1) {
      current[rightIndex] = Math.min(
        current[rightIndex - 1] + 1,
        previous[rightIndex] + 1,
        previous[rightIndex - 1] + (left[leftIndex - 1] === right[rightIndex - 1] ? 0 : 1),
      );
    }
    previous.splice(0, previous.length, ...current);
  }
  return previous[right.length];
}

function matchScore(query: string, candidate: string) {
  if (candidate === query) return 0;
  if (candidate.startsWith(query)) return 1 + (candidate.length - query.length) / 100;
  if (candidate.includes(query)) return 2 + candidate.indexOf(query) / 100;
  const distance = editDistance(query, candidate);
  const allowedDistance = query.length <= 4 ? 1 : query.length <= 8 ? 2 : 3;
  return distance <= allowedDistance ? 3 + distance / Math.max(query.length, candidate.length) : Number.POSITIVE_INFINITY;
}

export function searchSyrianCities(value: string, limit = 10): SyrianCity[] {
  const query = normalizeCitySearch(value);
  if (!query) return [];
  return cities
    .map(city => {
      const candidates = [city.name, city.region, ...city.aliases].map(normalizeCitySearch);
      return { city, score: Math.min(...candidates.map(candidate => matchScore(query, candidate))) };
    })
    .filter(item => Number.isFinite(item.score))
    .sort((left, right) => left.score - right.score || left.city.name.localeCompare(right.city.name, "ar"))
    .slice(0, limit)
    .map(({ city: { aliases: _aliases, ...city } }) => city);
}
