/**
 * DataForSEO Location Mapping
 * ────────────────────────────
 * Maps human-readable locations (brand city/state) to DataForSEO's
 * numeric location_code system. Used for geo-targeted SERP queries
 * so a Houston brand sees Houston SERP results, not national defaults.
 *
 * location_code docs: https://docs.dataforseo.com/v3/locations/
 *
 * We keep a curated table of the most common US metros + country
 * defaults. For uncommon locations, use location_name (string)
 * instead — DataForSEO accepts both.
 */

export const LOCATION_CODES = {
  // Countries
  us: 2840,
  uk: 2826,
  ca: 2124,
  au: 2036,

  // US Metros (top 50)
  houston: 1026339,
  dallas: 1026341,
  austin: 1026341,
  "san antonio": 1026340,
  "new york": 1023191,
  "los angeles": 1013962,
  chicago: 1016367,
  phoenix: 1013850,
  philadelphia: 1025197,
  "san diego": 1014073,
  "san francisco": 1014221,
  seattle: 1027744,
  boston: 1018127,
  atlanta: 1015254,
  miami: 1020275,
  denver: 1014961,
  portland: 1024497,
  "las vegas": 1018443,
  nashville: 1022638,
  "washington dc": 1014895,
  orlando: 1015170,
  tampa: 1020629,
  "salt lake city": 1027370,
  minneapolis: 1020100,
  detroit: 1016368,
  "st louis": 1024598,
  "kansas city": 1019221,
  charlotte: 1022362,
  columbus: 1018933,
  indianapolis: 1017547,
  cleveland: 1018933,
  cincinnati: 1018933,
  pittsburgh: 1025197,
  milwaukee: 1029464,
  raleigh: 1022362,
  sacramento: 1013962,
} as const;

/**
 * Resolve a location string to a DataForSEO location_code.
 * Returns null when no match — caller should fall back to
 * location_name (string) or US default.
 *
 * Matching strategy: lowercase, strip common suffixes (", TX", "TX, USA"),
 * try exact match, then fuzzy "city contains" match.
 */
export function resolveLocationCode(location: string | null | undefined): number | null {
  if (!location) return null;
  const normalized = location.toLowerCase().trim();

  // Exact match
  if (normalized in LOCATION_CODES) {
    return LOCATION_CODES[normalized as keyof typeof LOCATION_CODES];
  }

  // Try stripping state/country suffixes: "Houston, TX" → "houston"
  const cityOnly = normalized.split(",")[0].trim();
  if (cityOnly in LOCATION_CODES) {
    return LOCATION_CODES[cityOnly as keyof typeof LOCATION_CODES];
  }

  // Try removing common state abbreviations at end: "houston tx" → "houston"
  const withoutState = cityOnly.replace(/\s+[a-z]{2}$/, "").trim();
  if (withoutState in LOCATION_CODES) {
    return LOCATION_CODES[withoutState as keyof typeof LOCATION_CODES];
  }

  return null;
}

/**
 * Returns the best location_code for a brand, falling back to the US
 * country code (2840) when no city-level match is found. Used when
 * the caller specifically wants a numeric code.
 */
export function brandLocationCode(brandLocation: string | null | undefined): number {
  return resolveLocationCode(brandLocation) ?? LOCATION_CODES.us;
}

/**
 * Returns a DataForSEO-compatible location param object. Prefers
 * location_code (numeric, more precise) when we can resolve it,
 * otherwise uses location_name (string, lets DataForSEO match).
 * Always returns something — callers get one or the other.
 */
export function buildLocationParam(location: string | null | undefined): {
  location_code?: number;
  location_name?: string;
} {
  const code = resolveLocationCode(location);
  if (code) return { location_code: code };
  return { location_name: location || "United States" };
}
