DROP TABLE IF EXISTS buildings CASCADE;

CREATE TABLE buildings AS
WITH raw AS (
  SELECT
    osm_id,
    way,
    NULLIF(building, '') AS building_type,
    substring(replace(COALESCE(tags -> 'height', ''), ',', '.') FROM '[-+]?[0-9]+(\.[0-9]+)?')::real
      AS height_value,
    substring(replace(COALESCE(tags -> 'building:levels', ''), ',', '.') FROM '[-+]?[0-9]+(\.[0-9]+)?')::real
      AS levels_value
  FROM planet_osm_polygon
  WHERE building IS NOT NULL
    AND building <> ''
    AND building <> 'no'
),
normalized AS (
  SELECT
    osm_id,
    ST_SetSRID(
      ST_Multi(ST_CollectionExtract(ST_MakeValid(way), 3)),
      4326
    ) AS geom,
    building_type,
    height_value,
    levels_value
  FROM raw
)
SELECT
  osm_id,
  geom,
  CASE
    WHEN height_value IS NOT NULL AND height_value > 0 THEN height_value
    WHEN levels_value IS NOT NULL AND levels_value > 0 THEN levels_value * 3.0
    WHEN building_type IN ('garage', 'garages', 'shed') THEN 3.0
    WHEN building_type IN ('industrial', 'warehouse') THEN 8.0
    WHEN building_type IN ('church', 'cathedral') THEN 12.0
    ELSE 9.0
  END::real AS height_m,
  CASE
    WHEN levels_value IS NOT NULL AND levels_value > 0 THEN levels_value::integer
    ELSE NULL
  END AS levels,
  building_type,
  CASE
    WHEN height_value IS NOT NULL AND height_value > 0 THEN 'measured'
    ELSE 'estimated'
  END AS source
FROM normalized
WHERE NOT ST_IsEmpty(geom);

ALTER TABLE buildings ALTER COLUMN geom TYPE geometry(MultiPolygon, 4326)
  USING ST_SetSRID(geom, 4326);

CREATE INDEX IF NOT EXISTS buildings_geom_gix ON buildings USING GIST (geom);
CREATE INDEX IF NOT EXISTS buildings_height_idx ON buildings (height_m);
CREATE INDEX IF NOT EXISTS buildings_type_idx ON buildings (building_type);
ANALYZE buildings;
