import countries from "@/utils/multiselectCountry.json";

/**
 * Region groupings and the default Account Type / Account Status selections for
 * the campaign Target step.
 *
 * Region is a convenience selector over the existing `country` criterion — the
 * backend has no notion of regions, so picking one just adds/removes that
 * region's countries from the country filter.
 */

type CountryJson = { name: string; code: string };

const norm = (value: string) => value.toLowerCase().replace(/[^a-z0-9]/g, "");

// Country names in `member_profiles.country` are free text and don't always
// match the reference JSON (which itself carries oddities like "Korea, Republic
// of South Korea"), so every region is defined by ISO alpha-2 code and the
// lookup below maps whatever the DB holds back onto a code.
const CODE_BY_NAME: Record<string, string> = (() => {
  const map: Record<string, string> = {};
  (countries as CountryJson[]).forEach(({ name, code }) => {
    map[norm(name)] = code;
    map[norm(code)] = code;
  });
  return map;
})();

// Spellings the reference JSON doesn't carry but members do use.
const COUNTRY_ALIASES: Record<string, string> = {
  uk: "GB",
  greatbritain: "GB",
  england: "GB",
  scotland: "GB",
  wales: "GB",
  northernireland: "GB",
  unitedkingdomofgreatbritainandnorthernireland: "GB",
  uae: "AE",
  emirates: "AE",
  southkorea: "KR",
  republicofkorea: "KR",
  northkorea: "KP",
  ivorycoast: "CI",
  drc: "CD",
  democraticrepublicofthecongo: "CD",
  democraticrepublicofcongo: "CD",
  eswatini: "SZ",
  czechia: "CZ",
  burma: "MM",
  macau: "MO",
  vaticancity: "VA",
  palestine: "PS",
  easttimor: "TL",
  caboverde: "CV",
  holland: "NL",
  thenetherlands: "NL",
  turkiye: "TR",
  westernsahara: "EH", // absent from the reference JSON entirely

  russianfederation: "RU",
  syria: "SY",
  iran: "IR",
  laopdr: "LA",
  brunei: "BN",
  tanzania: "TZ",
  bolivia: "BO",
  venezuela: "VE",
};

/** ISO alpha-2 code for a raw country string, or null if unrecognised. */
export const countryCode = (value: string): string | null => {
  const key = norm(value);
  return CODE_BY_NAME[key] ?? COUNTRY_ALIASES[key] ?? null;
};

export interface RegionOption {
  value: string;
  label: string;
  codes: string[];
}

export const REGIONS: RegionOption[] = [
  { value: "india", label: "India", codes: ["IN"] },
  {
    value: "oceania",
    label: "Oceania",
    codes: [
      "AU",
      "NZ",
      "FJ",
      "PG",
      "SB",
      "VU",
      "NC",
      "PF",
      "WS",
      "AS",
      "TO",
      "TV",
      "KI",
      "NR",
      "NU",
      "CK",
      "PW",
      "FM",
      "MH",
      "GU",
      "MP",
      "NF",
      "TK",
      "WF",
      "PN",
    ],
  },
  {
    value: "south-east-asia",
    label: "South East Asia",
    codes: ["ID", "MY", "SG", "TH", "VN", "PH", "KH", "LA", "MM", "BN", "TL"],
  },
  {
    // India and South East Asia are their own regions, so they're excluded here
    // rather than double-counted.
    value: "asia-rest",
    label: "Asia (excl. India & South East Asia)",
    codes: [
      "CN",
      "HK",
      "MO",
      "TW",
      "JP",
      "KR",
      "KP",
      "MN",
      "NP",
      "BT",
      "BD",
      "LK",
      "MV",
      "PK",
      "AF",
      "KZ",
      "UZ",
      "TM",
      "KG",
      "TJ",
    ],
  },
  {
    value: "africa-middle-east",
    label: "Africa & Middle East",
    codes: [
      // Middle East
      "AE",
      "SA",
      "QA",
      "KW",
      "BH",
      "OM",
      "YE",
      "IQ",
      "IR",
      "IL",
      "JO",
      "LB",
      "SY",
      "PS",
      "TR",
      // Africa
      "DZ",
      "AO",
      "BJ",
      "BW",
      "BF",
      "BI",
      "CM",
      "CV",
      "CF",
      "TD",
      "KM",
      "CG",
      "CD",
      "CI",
      "DJ",
      "EG",
      "GQ",
      "ER",
      "ET",
      "GA",
      "GM",
      "GH",
      "GN",
      "GW",
      "KE",
      "LS",
      "LR",
      "LY",
      "MG",
      "MW",
      "ML",
      "MR",
      "MU",
      "MA",
      "MZ",
      "NA",
      "NE",
      "NG",
      "RW",
      "ST",
      "SN",
      "SC",
      "SL",
      "SO",
      "ZA",
      "SS",
      "SD",
      "SZ",
      "TZ",
      "TG",
      "TN",
      "UG",
      "ZM",
      "ZW",
      "RE",
      "YT",
      "EH",
      "SH",
    ],
  },
  {
    value: "europe",
    label: "Europe (incl. UK & Eastern Europe)",
    codes: [
      "AL",
      "AD",
      "AM",
      "AT",
      "AZ",
      "BY",
      "BE",
      "BA",
      "BG",
      "HR",
      "CY",
      "CZ",
      "DK",
      "EE",
      "FI",
      "FR",
      "GE",
      "DE",
      "GR",
      "HU",
      "IS",
      "IE",
      "IT",
      "LV",
      "LI",
      "LT",
      "LU",
      "MT",
      "MD",
      "MC",
      "ME",
      "NL",
      "MK",
      "NO",
      "PL",
      "PT",
      "RO",
      "RU",
      "SM",
      "RS",
      "SK",
      "SI",
      "ES",
      "SE",
      "CH",
      "UA",
      "GB",
      "VA",
      "FO",
      "GI",
      "GG",
      "JE",
      "IM",
      "AX",
    ],
  },
];

export const REGION_SELECT_DATA = REGIONS.map(({ value, label }) => ({
  value,
  label,
}));

/**
 * The subset of `available` (the countries the member DB actually holds) that
 * falls inside the given regions. Countries the lookup can't place — and every
 * country outside these six regions, e.g. the Americas — are simply never
 * returned and stay available to pick by hand.
 */
export const countriesInRegions = (
  regions: string[],
  available: string[],
): string[] => {
  if (regions.length === 0) return [];
  const codes = new Set(
    REGIONS.filter((r) => regions.includes(r.value)).flatMap((r) => r.codes),
  );
  return available.filter((country) => {
    const code = countryCode(country);
    return code !== null && codes.has(code);
  });
};

/** Account Types pre-selected on a new campaign. */
export const DEFAULT_ACCOUNT_TYPES = [
  "KRR & Karma Residences",
  "Full Owner & KRR",
  "Karma Royal Residences",
  "Karma Residences",
  "Week & PTS Member",
  "Weeks Member",
  "Points Member",
  "KRR & Week",
  "Karma Residences & KC",
  "KRR & KC",
  "Karma Club 2021",
  "Karma Club",
  "Normandy Owner",
  "Full Owner",
  "Points Club",
];

/** Account Statuses pre-selected on a new campaign. */
export const DEFAULT_ACCOUNT_STATUSES = [
  "Active",
  "Active - 50%",
  "Active/Open",
  "Active/Open-Arrears",
  "Active/Finance-Arrears",
  "Active/Finance Open",
  "Active/Installments",
];

/**
 * Option values whose labels match `names`, compared without case, spacing or
 * punctuation ("Active - 50%" matches "Active-50%"). Names with no matching
 * option are skipped — the defaults list is maintained by hand and the member
 * DB is the source of truth for what actually exists.
 */
export const optionValuesByLabel = (
  names: string[],
  options: { label?: string; value: string }[],
): string[] => {
  const wanted = new Set(names.map(norm));
  return options
    .filter((o) => o.label && wanted.has(norm(o.label)))
    .map((o) => o.value);
};
