/**
 * Pure logic for Saved Places (Home / Work / favourites) — kept dependency
 * free (no AsyncStorage, no React) so it can be unit tested under Node
 * without pulling in `expo`/`react-native` (see vitest.config.ts).
 */
import type { SearchResult } from "../types";

export type SavedPlaceKind = "home" | "work" | "favourite";

export type SavedPlace = SearchResult & {
  id: string;
  label: string;
  kind: SavedPlaceKind;
};

/**
 * Deterministic id — never Date.now()/Math.random(), so results are
 * reproducible in tests and stable across a reload of the same list.
 * Home and Work are singletons, so they're keyed by kind alone (a second
 * "set home" naturally replaces the first). Favourites are keyed by a hash
 * of name + coordinates so re-saving the same place updates it in place
 * instead of appending a duplicate.
 */
export function makeSavedId(kind: SavedPlaceKind, place: SearchResult): string {
  if (kind === "home" || kind === "work") return kind;
  return `favourite-${hashPlace(place)}`;
}

function hashPlace(place: SearchResult): string {
  const key = `${place.name}|${place.position.latitude}|${place.position.longitude}`;
  let hash = 0;
  for (let i = 0; i < key.length; i += 1) {
    hash = (hash * 31 + key.charCodeAt(i)) | 0;
  }
  return Math.abs(hash).toString(36);
}

function defaultLabel(kind: SavedPlaceKind, place: SearchResult): string {
  if (kind === "home") return "Home";
  if (kind === "work") return "Work";
  return place.name;
}

/**
 * Adds (or replaces) a saved place. Home and Work are singletons — adding a
 * new one replaces the old entry of that kind rather than appending.
 * Favourites dedupe by id (same name + coordinates), so re-adding one just
 * updates its label.
 */
export function addSavedPlace(
  saved: SavedPlace[],
  place: SearchResult,
  kind: SavedPlaceKind,
  label?: string
): SavedPlace[] {
  const id = makeSavedId(kind, place);
  const entry: SavedPlace = {
    ...place,
    id,
    kind,
    label: label ?? defaultLabel(kind, place),
  };
  const withoutSingletonOrDuplicate = saved.filter((existing) =>
    kind === "home" || kind === "work" ? existing.kind !== kind : existing.id !== id
  );
  return [...withoutSingletonOrDuplicate, entry];
}

export function removeSavedPlace(saved: SavedPlace[], id: string): SavedPlace[] {
  return saved.filter((entry) => entry.id !== id);
}

export function getHome(saved: SavedPlace[]): SavedPlace | undefined {
  return saved.find((entry) => entry.kind === "home");
}

export function getWork(saved: SavedPlace[]): SavedPlace | undefined {
  return saved.find((entry) => entry.kind === "work");
}

export function getFavourites(saved: SavedPlace[]): SavedPlace[] {
  return saved.filter((entry) => entry.kind === "favourite");
}
