-- pSEO article data: per-city padel cost and market analysis.
-- One row per city — consumed by the city-cost-de.md.jinja template to generate
-- ~600 city-level articles about padel investment costs.
--
-- Calculator override columns use camelCase to match the DEFAULTS keys in
-- planner/calculator.py, so they are auto-applied as calc pre-fills.
--
-- Cost override columns come from foundation.dim_countries (Eurostat PLI and energy
-- price indices). NULL = fall through to calculator.py DEFAULTS (safe: auto-mapping
-- filters None). DE always produces NULL overrides — preserves exact DEFAULTS behaviour.

MODEL (
  name serving.pseo_city_costs_de,
  kind FULL,
  cron '@daily',
  grain city_key
);

SELECT
  -- Composite natural key: country_slug + city_slug ensures uniqueness across countries
  -- (city_slug alone is not unique — 'valencia' exists in ES, VE, etc.)
  c.country_slug || '-' || c.city_slug  AS city_key,
  -- City identity
  c.city_slug,
  c.city_name,
  c.country_code,
  c.country_name_en,
  c.country_slug,
  -- City coordinates (for the city venue dot map)
  c.lat,
  c.lon,
  -- Market metrics
  c.population,
  c.city_padel_venue_count AS padel_venue_count,
  c.city_venues_per_100k AS venues_per_100k,
  c.market_score,
  c.opportunity_score,
  c.data_confidence,
  -- Pricing (from Playtomic, NULL when no coverage)
  c.median_hourly_rate,
  c.median_peak_rate,
  c.median_offpeak_rate,
  c.median_occupancy_rate,
  c.median_daily_revenue_per_venue,
  COALESCE(c.price_currency, p.price_currency, 'EUR') AS price_currency,
  -- Calculator override columns — camelCase keys match planner DEFAULTS auto-mapping.
  -- utilTarget: planner stores 0.0–1.0, calculator expects 0–100.
  p.rate_peak                       AS "ratePeak",
  p.rate_off_peak                   AS "rateOffPeak",
  p.avg_utilisation_pct * 100       AS "utilTarget",
  FLOOR(p.courts_typical)           AS "dblCourts",
  -- 'country' drives currency formatting in the calculator
  c.country_code                    AS "country",
  -- Cost override columns from dim_countries (Eurostat PLI + energy price indices).
  -- NULL = fall through to calculator.py DEFAULTS. DE always NULL (baseline preserved).
  -- OPEX overrides
  cc.electricity                    AS "electricity",
  cc.heating                        AS "heating",
  cc.rent_sqm                       AS "rentSqm",
  cc.insurance                      AS "insurance",
  cc.cleaning                       AS "cleaning",
  cc.maintenance                    AS "maintenance",
  cc.marketing                      AS "marketing",
  cc.water                          AS "water",
  cc.property_tax                   AS "propertyTax",
  cc.outdoor_rent                   AS "outdoorRent",
  -- CAPEX overrides
  cc.hall_cost_sqm                  AS "hallCostSqm",
  cc.foundation_sqm                 AS "foundationSqm",
  cc.land_price_sqm                 AS "landPriceSqm",
  cc.hvac                           AS "hvac",
  cc.electrical                     AS "electrical",
  cc.sanitary                       AS "sanitary",
  cc.parking                        AS "parking",
  cc.fitout                         AS "fitout",
  cc.planning                       AS "planning",
  cc.fire_protection                AS "fireProtection",
  cc.floor_prep                     AS "floorPrep",
  cc.hvac_upgrade                   AS "hvacUpgrade",
  cc.lighting_upgrade               AS "lightingUpgrade",
  cc.outdoor_foundation             AS "outdoorFoundation",
  cc.outdoor_site_work              AS "outdoorSiteWork",
  cc.outdoor_lighting               AS "outdoorLighting",
  cc.outdoor_fencing                AS "outdoorFencing",
  cc.working_capital                AS "workingCapital",
  cc.permits_compliance             AS "permitsCompliance",
  CURRENT_DATE                      AS refreshed_date
FROM serving.location_profiles c
LEFT JOIN serving.planner_defaults p
  ON c.country_code = p.country_code
  AND c.city_slug = p.city_slug
LEFT JOIN foundation.dim_countries cc
  ON c.country_code = cc.country_code
-- Only cities with actual padel presence and at least some rate data
WHERE c.city_slug IS NOT NULL
  AND c.city_padel_venue_count > 0
  AND (p.rate_peak IS NOT NULL OR c.median_peak_rate IS NOT NULL)
