-- NUTS-2 boundary polygons from Eurostat GISCO for spatial income resolution.
-- Used by dim_locations to resolve each location's (lat, lon) to its NUTS-2
-- region via ST_Contains point-in-polygon join.
--
-- Source: data/landing/gisco/2024/01/nuts2_boundaries.geojson
-- Downloaded by: scripts/download_gisco_nuts.py (run once; re-run on NUTS revision)
-- Format: GeoJSON FeatureCollection with NUTS_ID, CNTR_CODE, NAME_LATN properties
-- NUTS revision: 2021 (effective 2024-01-01); changes ~every 7 years
--
-- Coverage: EU-27 + EFTA (NO, CH, IS, LI) + UK + candidate countries
-- ~242 NUTS-2 polygons at 1:20,000,000 scale (simplified for performance)

MODEL (
  name staging.stg_nuts2_boundaries,
  kind FULL,
  cron '@daily',
  grain nuts2_code
);

WITH raw AS (
  -- ST_Read reads GeoJSON via GDAL. File must be uncompressed (.geojson, not .gz).
  -- Path is fixed (not glob) because the boundary file is a one-time download,
  -- not a time-partitioned series. The partition "2024/01" reflects the NUTS
  -- revision year, not the download date.
  SELECT *
  FROM ST_Read(@LANDING_DIR || '/gisco/2024/01/nuts2_boundaries.geojson')
)
SELECT
  NUTS_ID                                      AS nuts2_code,
  -- Normalise country prefix to ISO 3166-1 alpha-2: EL→GR, UK→GB
  @normalize_eurostat_country(CNTR_CODE)       AS country_code,
  NAME_LATN                                    AS region_name,
  geom                                         AS geometry,
  -- Pre-compute bounding box for efficient spatial pre-filter in dim_locations.
  -- Each location only calls ST_Contains against the ~3-5 polygons whose bbox
  -- overlaps it, not all 242.
  ST_YMin(geom)                                AS bbox_lat_min,
  ST_YMax(geom)                                AS bbox_lat_max,
  ST_XMin(geom)                                AS bbox_lon_min,
  ST_XMax(geom)                                AS bbox_lon_max
FROM raw
WHERE NUTS_ID IS NOT NULL
  AND LENGTH(NUTS_ID) = 4  -- NUTS-2 codes are exactly 4 characters
