import type { AuditLocation } from "./db";

/**
 * Intelligent Human-Readable Location Formatter
 *
 * Rules:
 *  1. Never fabricates a street name or house number.
 *  2. Combines only genuinely returned fields: [road, locality, city, region, country].
 *  3. Filters duplicates (e.g. if city equals region, or locality equals city).
 *  4. Gracefully degrades:
 *     - road + locality + city + region + country
 *     - locality + city + region + country
 *     - city + region + country
 *     - region + country
 *     - country
 *  5. If address is explicitly set, cleans and uses it.
 *  6. If no textual fields are available, falls back to coordinates without crashing.
 */
export function formatLocationDisplay(location?: Partial<AuditLocation> | null): string {
  if (!location) return "—";

  if (location.status === "denied") return "Location access denied";
  if (location.status === "unavailable") return "Location unavailable";

  // If a pre-formatted human-readable address is provided and non-trivial
  if (location.address && location.address.trim().length > 0) {
    return cleanFormattedAddress(location.address);
  }

  const rawParts = [
    location.locality,
    location.city,
    location.region,
    location.country,
  ];

  const uniqueParts: string[] = [];
  for (const p of rawParts) {
    if (!p) continue;
    const clean = p.trim();
    if (!clean) continue;
    // Avoid adjacent or case-insensitive duplicates (e.g., "Jaipur, Jaipur")
    const alreadyExists = uniqueParts.some(
      (existing) => existing.toLowerCase() === clean.toLowerCase()
    );
    if (!alreadyExists) {
      uniqueParts.push(clean);
    }
  }

  if (uniqueParts.length > 0) {
    return uniqueParts.join(", ");
  }

  // Fallback to coordinates if available
  if (location.latitude != null && location.longitude != null) {
    return `${Number(location.latitude).toFixed(4)}, ${Number(location.longitude).toFixed(4)}`;
  }

  return "Location unavailable";
}

/**
 * Normalizes and formats address string from reverse geocoder data.
 */
export function cleanFormattedAddress(addr: string): string {
  return addr
    .split(",")
    .map((s) => s.trim())
    .filter((s, idx, arr) => s.length > 0 && arr.indexOf(s) === idx)
    .join(", ");
}

/**
 * Converts BigDataCloud reverse geocode client response into structured AuditLocation
 */
export function buildLocationFromBigDataCloud(
  lat: number,
  lon: number,
  geoData: any
): AuditLocation {
  const road = geoData?.localityInfo?.administrative?.find?.(
    (a: any) => a.order === 11 || a.adminLevel === 11
  )?.name || "";

  const locality =
    geoData?.locality ||
    geoData?.localityInfo?.administrative?.find?.((a: any) => a.order === 8)?.name ||
    geoData?.suburb ||
    geoData?.neighbourhood ||
    "";

  const city =
    geoData?.city ||
    geoData?.localityInfo?.administrative?.find?.((a: any) => a.order === 6)?.name ||
    locality ||
    "";

  const region =
    geoData?.principalSubdivision ||
    geoData?.localityInfo?.administrative?.find?.((a: any) => a.order === 4)?.name ||
    "";

  const country =
    geoData?.countryName ||
    geoData?.localityInfo?.administrative?.find?.((a: any) => a.order === 2)?.name ||
    "";

  const postalCode = geoData?.postcode || "";

  // Intelligent display address construction following Part 4
  const addressParts = [road, locality, city, region, country].filter(
    (v, i, arr) => Boolean(v) && arr.indexOf(v) === i
  );

  const address = addressParts.join(", ");

  return {
    status: "available",
    latitude: Number(lat.toFixed(5)),
    longitude: Number(lon.toFixed(5)),
    address: address || undefined,
    locality: locality || undefined,
    city: city || undefined,
    region: region || undefined,
    country: country || undefined,
    postalCode: postalCode || undefined,
    source: "browser-geolocation-reverse-geocode",
    capturedAt: new Date().toISOString(),
  };
}
