/**
 * Schreibt einen Ortsnamen lesbar groß: erster Buchstabe sowie Buchstaben
 * nach Leerzeichen oder Bindestrich werden großgeschrieben.
 * Beispiele: "augsburg" -> "Augsburg", "baden-baden" -> "Baden-Baden".
 */
export function capitalizeCity(city: string): string {
  return city.replace(/(^|[\s-])(\w)/g, (_, prefix, char) => prefix + char.toUpperCase());
}

/**
 * Baut eine lesbare Adresse aus Straßenzeile, optional Stadtteil, PLZ und Stadt.
 * Formate:
 *   - mit Stadtteil: "Strasse Hausnummer, Stadtteil, PLZ Stadt"
 *     (z.B. "Testweg 1, Daxlanden, 76185 Karlsruhe")
 *   - ohne Stadtteil: "Strasse Hausnummer, PLZ Stadt"
 *     (z.B. "Erbprinzenstrasse 31, 76133 Karlsruhe")
 * Fehlt ein Teil, wird er weggelassen statt eines Platzhalters.
 */
export function buildAddressDisplay(
  streetLine?: string | null,
  postalCode?: string | null,
  city?: string | null,
  suburb?: string | null,
): string | undefined {
  const normalizedCity = city ? capitalizeCity(city.trim()) : undefined;
  const normalizedSuburb = suburb ? capitalizeCity(suburb.trim()) : undefined;
  const location = [postalCode, normalizedCity].filter(Boolean).join(' ');

  let trimmedStreet = streetLine?.trim();

  // Falls die Straßenzeile bereits mit der Stadt endet (z.B. weil ältere
  // Sponsor-Daten Stadt in address mitgespeichert haben), Stadt entfernen,
  // damit sie nicht doppelt erscheint.
  if (trimmedStreet && normalizedCity) {
    const cityLower = normalizedCity.toLowerCase();
    const streetLower = trimmedStreet.toLowerCase();
    if (streetLower.endsWith(cityLower)) {
      trimmedStreet = trimmedStreet.slice(0, -normalizedCity.length).replace(/,\s*$/, '').trim();
    }
  }

  const parts = [trimmedStreet, normalizedSuburb, location].filter(Boolean);
  if (parts.length === 0) return undefined;
  return parts.join(', ');
}

/**
 * Normalisiert Adress-Strings fuer die Anzeige.
 *
 * Hintergrund: lib/overpass.ts baut NEUE Adressen bereits korrekt als
 * "Strasse Hausnummer, PLZ Stadt". Bereits im restaurants-Cache liegende Zeilen
 * (vor diesem Fix eingefuegt) haben aber noch das alte, kommalose Format
 * "Strasse Hausnummer Stadt" - und werden erst beim naechsten Overpass-Refetch
 * (Cache-TTL 20 Min, siehe restaurants-Route) ueberschrieben. Diese Funktion
 * reformatiert daher AUCH auf der Anzeige-Seite als Sicherheitsnetz, statt auf
 * den naechsten Cache-Refresh zu warten.
 *
 * Optional koennen PLZ und Stadt separat uebergeben werden, z.B. fuer
 * gesponserte Restaurants, bei denen Adresse, PLZ und Stadt getrennt gespeichert
 * sind. In dem Fall wird aus "Strasse" + "PLZ" + "Stadt" ein einheitlicher
 * Anzeige-String gebaut.
 *
 * Heuristik: findet das letzte Token, das wie eine Hausnummer aussieht
 * (z.B. "31", "12a", "3-5"), und setzt danach ein Komma vor den Stadt-Teil.
 * Strings mit bereits vorhandenem Komma werden unveraendert zurueckgegeben.
 */
export function normalizeAddressDisplay(
  raw: string | null | undefined,
  postalCode?: string | null,
  city?: string | null,
  suburb?: string | null,
): string | undefined {
  // Wenn keine Straße vorliegt, aber PLZ und/oder Stadt separat gegeben sind,
  // bauen wir daraus einen reinen Orts-String.
  if (!raw) {
    return buildAddressDisplay(undefined, postalCode, city, suburb);
  }

  const trimmed = raw.trim();
  if (!trimmed) {
    return buildAddressDisplay(undefined, postalCode, city, suburb);
  }

  // Bereits zusammengesetzte Adresse (z.B. aus OSM oder buildAddressDisplay).
  // Endet sie nur mit der PLZ (ohne Stadt), wird die separat übergebene Stadt
  // angehängt, z.B. "Kriegsstraße 218, 76135" -> "Kriegsstraße 218, 76135 Karlsruhe".
  if (trimmed.includes(',')) {
    const postcodeOnlyMatch = trimmed.match(/, (\d{5})$/);
    if (postcodeOnlyMatch && city) {
      return `${trimmed} ${capitalizeCity(city.trim())}`;
    }
    return trimmed;
  }

  const tokens = trimmed.split(/\s+/);
  const houseNumberRegex = /^\d+[a-zA-Z]?(-\d+)?$/;

  let splitIndex = -1;
  for (let i = tokens.length - 1; i >= 0; i--) {
    if (houseNumberRegex.test(tokens[i])) {
      splitIndex = i;
      break;
    }
  }

  // Keine Hausnummer gefunden, oder Hausnummer ist bereits das letzte Token
  // (kein Stadt-Teil danach) -> Original als Straßenzeile verwenden.
  if (splitIndex === -1 || splitIndex === tokens.length - 1) {
    return buildAddressDisplay(trimmed, postalCode, city, suburb);
  }

  const street = tokens.slice(0, splitIndex + 1).join(' ');
  const rawCity = tokens.slice(splitIndex + 1).join(' ');
  // Falls separat PLZ/Stadt übergeben wurden, haben diese Vorrang vor dem
  // aus dem String geratenen Rest.
  const effectiveCity = city || rawCity;
  return buildAddressDisplay(street, postalCode, effectiveCity, suburb);
}
