-- PostGIS schema for the trip planner (runs once, on first container boot).
-- osm2pgsql loads the standard planet_osm_* tables; we then materialize the
-- POI points we query on, with a GIST index for ST_DWithin / KNN.

CREATE EXTENSION IF NOT EXISTS postgis;
-- osm2pgsql --hstore puts every tag that has no dedicated column here
CREATE EXTENSION IF NOT EXISTS hstore;

-- Named data sets (so multi-extract setups — e.g. northeast + colombia — can
-- be imported into one DB and disambiguated).
CREATE TABLE IF NOT EXISTS spatial_extract (
    name        text PRIMARY KEY,
    imported_at timestamptz NOT NULL DEFAULT now(),
    bounds      box,                 -- from osmium (in degrees)
    poi_count   bigint
);

-- Searchable POIs: every named point/polygon of the interesting kinds.
-- osm2pgsql 2.x pgsql output schema: planet_osm_point / planet_osm_polygon,
-- geometry in EPSG:3857 in a column called `way`; tags without a dedicated
-- column (opening_hours, fee, website, addr:*) live in the hstore `tags`.
CREATE TABLE IF NOT EXISTS poi (
    extract       text   NOT NULL REFERENCES spatial_extract(name) ON DELETE CASCADE,
    osm_id        bigint NOT NULL,
    osm_type      char   NOT NULL,            -- 'N' | 'W'
    name          text   NOT NULL,
    kind          text   NOT NULL,            -- dominant tag: amenity=, tourism=, …
    amenity       text,
    tourism       text,
    shop          text,
    leisure       text,
    historic      text,
    place         text,
    opening_hours text,
    fee           text,                        -- OSM fee tag / fee:* values
    website       text,
    addr_city     text,
    geom          geometry(Point, 4326) NOT NULL,   -- reprojected from 3857
    PRIMARY KEY (extract, osm_type, osm_id)
);

CREATE INDEX IF NOT EXISTS poi_geom_gist ON poi USING GIST (geom);
CREATE INDEX IF NOT EXISTS poi_kind ON poi (extract, kind);
CREATE INDEX IF NOT EXISTS poi_name_trgm ON poi USING GIN (to_tsvector('simple', name));

-- pgvector (semantic POI index) is a later milestone: it needs the vector
-- package in the image (postgis/postgis doesn't ship it), so it gets its own
-- init script + embedding importer instead of living in this base schema.

-- Helper: refresh the poi table from a freshly loaded extract.
-- (Invoked by import.sh; kept here so the SQL lives in one place.)
CREATE OR REPLACE FUNCTION refresh_poi(p_extract text) RETURNS void AS $$
BEGIN
    DELETE FROM poi WHERE extract = p_extract;
    INSERT INTO poi (extract, osm_id, osm_type, name, kind, amenity, tourism, shop,
                     leisure, historic, place, opening_hours, fee, website, addr_city, geom)
    WITH cand AS (
        SELECT 'N'::char AS t, n.osm_id, n.name, n.amenity, n.tourism, n.shop,
               n.leisure, n.historic, n.place,
               n.tags->>'opening_hours'                        AS opening_hours,
               COALESCE(n.tags->>'fee', n.tags->>'fee:tourism') AS fee,
               COALESCE(n.tags->>'website', n.tags->>'url')     AS website,
               n.tags->>'addr:city'                             AS addr_city,
               ST_Transform(n.way, 4326)                        AS geom
        FROM planet_osm_point n
        WHERE n.name IS NOT NULL AND n.name <> ''
          AND (n.amenity IS NOT NULL OR n.tourism IS NOT NULL OR n.shop IS NOT NULL
               OR n.leisure IS NOT NULL OR n.historic IS NOT NULL OR n.place IS NOT NULL)
        UNION ALL
        SELECT 'W'::char, w.osm_id, w.name, w.amenity, w.tourism, w.shop,
               w.leisure, w.historic, w.place,
               w.tags->>'opening_hours',
               COALESCE(w.tags->>'fee', w.tags->>'fee:tourism'),
               COALESCE(w.tags->>'website', w.tags->>'url'),
               w.tags->>'addr:city',
               ST_Centroid(ST_Transform(w.way, 4326))
        FROM planet_osm_polygon w
        WHERE w.name IS NOT NULL AND w.name <> ''
          AND (w.amenity IS NOT NULL OR w.tourism IS NOT NULL OR w.shop IS NOT NULL
               OR w.leisure IS NOT NULL OR w.historic IS NOT NULL)
    )
    SELECT p_extract, osm_id, t, name,
           COALESCE(
             CASE WHEN amenity    IS NOT NULL THEN 'amenity='    || amenity
                  END,
             CASE WHEN tourism    IS NOT NULL THEN 'tourism='    || tourism
                  END,
             CASE WHEN shop       IS NOT NULL THEN 'shop='       || shop
                  END,
             CASE WHEN leisure    IS NOT NULL THEN 'leisure='    || leisure
                  END,
             CASE WHEN historic   IS NOT NULL THEN 'historic='   || historic
                  END,
             CASE WHEN place      IS NOT NULL THEN 'place='      || place
                  END
           ),
           amenity, tourism, shop, leisure, historic, place,
           opening_hours, fee, website, addr_city, geom
    FROM cand
    WHERE COALESCE(amenity, tourism, shop, leisure, historic, place) IS NOT NULL;

    UPDATE spatial_extract
       SET poi_count = (SELECT count(*) FROM poi WHERE extract = p_extract),
           imported_at = now()
     WHERE name = p_extract;

    ANALYZE poi;
END;
$$ LANGUAGE plpgsql;
