import { describe, expect, it } from "vitest";
import {
  TAP_TOLERANCE_PX,
  droppedPin,
  featureName,
  pickPlaceFromFeatures,
  tapToleranceBox,
} from "./tapSelection";
import type { LatLng } from "../../modules/mapmap-react-native/src/MapmapNav.types";

const position: LatLng = { latitude: 51.5074, longitude: -0.1278 };

function feature(properties: Record<string, unknown> | null): GeoJSON.Feature {
  return {
    type: "Feature",
    geometry: { type: "Point", coordinates: [0, 0] },
    properties,
  };
}

describe("featureName", () => {
  it("reads a plain OpenMapTiles name", () => {
    expect(featureName(feature({ name: "The Ivy" }))).toBe("The Ivy");
  });

  it("falls back to name:en then name:latin", () => {
    expect(featureName(feature({ "name:en": "Kyiv" }))).toBe("Kyiv");
    expect(featureName(feature({ "name:latin": "München" }))).toBe("München");
  });

  it("prefers name over the localised keys", () => {
    expect(featureName(feature({ name: "A", "name:en": "B" }))).toBe("A");
  });

  it("ignores blank / non-string / missing names", () => {
    expect(featureName(feature({ name: "   " }))).toBeNull();
    expect(featureName(feature({ name: 42 }))).toBeNull();
    expect(featureName(feature(null))).toBeNull();
    expect(featureName(feature({}))).toBeNull();
  });

  it("trims surrounding whitespace", () => {
    expect(featureName(feature({ name: "  Big Ben  " }))).toBe("Big Ben");
  });
});

describe("tapToleranceBox", () => {
  it("builds a finger-sized box around the point", () => {
    expect(tapToleranceBox([100, 200], 9)).toEqual([
      [91, 191],
      [109, 209],
    ]);
  });

  it("defaults to the tap tolerance", () => {
    const [[left, top], [right, bottom]] = tapToleranceBox([0, 0]);
    expect(right - left).toBe(TAP_TOLERANCE_PX * 2);
    expect(bottom - top).toBe(TAP_TOLERANCE_PX * 2);
  });
});

describe("droppedPin", () => {
  it("uses the coordinate as the address", () => {
    expect(droppedPin(position)).toEqual({
      name: "Dropped pin",
      address: "51.50740, -0.12780",
      position,
    });
  });
});

describe("pickPlaceFromFeatures", () => {
  it("selects the first named feature (POI wins over incidental geometry)", () => {
    const features = [
      feature(null),
      feature({ name: "Regent's Park", address: "NW1" }),
      feature({ name: "Later ignored" }),
    ];
    expect(pickPlaceFromFeatures(features, position)).toEqual({
      name: "Regent's Park",
      address: "NW1",
      position,
    });
  });

  it("reads a POI name under name:en", () => {
    const place = pickPlaceFromFeatures([feature({ "name:en": "British Museum" })], position);
    expect(place.name).toBe("British Museum");
    expect(place.address).toBe("");
  });

  it("uses addr:street when no address property is present", () => {
    const place = pickPlaceFromFeatures(
      [feature({ name: "Café", "addr:street": "Baker Street" })],
      position
    );
    expect(place.address).toBe("Baker Street");
  });

  it("drops a pin when nothing under the tap is named", () => {
    expect(pickPlaceFromFeatures([feature(null), feature({})], position)).toEqual(
      droppedPin(position)
    );
  });

  it("drops a pin on an empty feature list", () => {
    expect(pickPlaceFromFeatures([], position)).toEqual(droppedPin(position));
  });
});
