-- 18_trigger_location_geom.sql — fleettickets · precise geoms survive re-upserts.
-- (migration 17 is 17_drop_unused_geo_indexes.sql — a parallel 260702 change.)
-- ─────────────────────────────────────────────────────────────────────────────
-- FT-BUG-01 (260702 audit): tg_ticket_geom resolved feed coords → cluster
-- centroid → none, NEVER consulting tickets.geo_locations. So the precise
-- location geocodes (808 keys, paid LocationIQ budget) were only applied by the
-- manual --geocode-* commands' resolve pass — and the very next 20-minute delta
-- ingest re-upserted changed rows and the trigger downgraded them back to the
-- cluster centroid. Live effect: 51 of 114k INC rows (and 0 CRQ) carried
-- geo_source='location'.
--
-- Fix: the trigger now resolves feed → LOCATION (geo_locations by
-- norm_cluster(location_name)) → cluster → none, mirroring
-- resolve_ticket_geoms()'s precedence exactly. Then one resolve pass repairs the
-- whole backlog immediately.
-- Idempotent — CREATE OR REPLACE + a re-runnable resolve.
-- ─────────────────────────────────────────────────────────────────────────────

CREATE OR REPLACE FUNCTION tickets.tg_ticket_geom()
 RETURNS trigger LANGUAGE plpgsql AS $fn$
DECLARE
  v_lat double precision := NULLIF(NEW.raw->>'latitude','')::double precision;
  v_lng double precision := NULLIF(NEW.raw->>'longitude','')::double precision;
  g geometry(Point, 4326);
BEGIN
  IF TG_OP = 'UPDATE' AND NEW.raw IS NOT DISTINCT FROM OLD.raw THEN
    RETURN NEW;                                -- geom/geo_source-only update — keep caller's value
  END IF;
  IF v_lat IS NOT NULL AND v_lng IS NOT NULL
     AND v_lat BETWEEN -90 AND 90 AND v_lng BETWEEN -180 AND 180
     AND NOT (v_lat = 0 AND v_lng = 0) THEN
    NEW.geom := ST_SetSRID(ST_MakePoint(v_lng, v_lat), 4326);
    NEW.geo_source := 'feed';
    RETURN NEW;
  END IF;
  -- [mig-18] precise location geocode BEFORE the coarse cluster centroid
  SELECT gl.geom INTO g FROM tickets.geo_locations gl
   WHERE gl.query_key = tickets.norm_cluster(NEW.raw->>'location_name')
     AND gl.geom IS NOT NULL LIMIT 1;
  IF g IS NOT NULL THEN
    NEW.geom := g; NEW.geo_source := 'location';
    RETURN NEW;
  END IF;
  SELECT gc.geom INTO g FROM tickets.geo_clusters gc
   WHERE gc.cluster_key = tickets.norm_cluster(NEW.raw->>'cluster')
     AND gc.geom IS NOT NULL LIMIT 1;
  IF g IS NOT NULL THEN NEW.geom := g; NEW.geo_source := 'cluster';
  ELSE NEW.geom := NULL; NEW.geo_source := 'none'; END IF;
  RETURN NEW;
END $fn$;

-- Repair the backlog now: re-resolve every non-feed row against the gazetteer
-- (resolve_ticket_geoms already prefers geo_locations over geo_clusters and only
-- touches rows whose geom/geo_source would actually change).
SELECT tickets.resolve_ticket_geoms();
