-- One Big Table: per-city padel market intelligence.
-- Consumed by: SEO article generation, planner city-select pre-fill, API endpoints.
--
-- Padelnomics Marktreife-Score v3 (0–100):
-- Answers "How mature/established is this padel market?"
-- Only computed for cities with ≥1 padel venue (padel_venue_count > 0).
-- For white-space opportunity scoring, see serving.location_opportunity_profile.
--
--   40 pts  supply development — log-scaled density (LN ceiling 20/100k) × count gate
--                                (min(1, count/5) kills small-town inflation)
--   25 pts  demand evidence   — occupancy when available; 40% density proxy otherwise
--   15 pts  addressable market — log-scaled population, ceiling 1M (context only)
--   10 pts  economic context  — income PPS normalised to 200 ceiling
--   10 pts  data quality      — completeness discount
--   No saturation discount: high density = maturity, not a penalty

MODEL (
  name serving.city_market_profile,
  kind FULL,
  cron '@daily',
  grain (country_code, city_slug)
);

WITH base AS (
  SELECT
    c.country_code,
    c.country_name_en,
    c.country_slug,
    c.city_name,
    c.city_slug,
    c.lat,
    c.lon,
    c.population,
    c.population_year,
    c.padel_venue_count,
    c.median_income_pps,
    c.income_year,
    c.geoname_id,
    -- Venue density: padel venues per 100K residents
    CASE WHEN c.population > 0
      THEN ROUND(c.padel_venue_count::DOUBLE / c.population * 100000, 2)
      ELSE NULL
    END                          AS venues_per_100k,
    -- Data confidence: 1.0 if both population and venues are present
    CASE
      WHEN c.population > 0 AND c.padel_venue_count > 0 THEN 1.0
      WHEN c.population > 0 OR  c.padel_venue_count > 0 THEN 0.5
      ELSE 0.0
    END                          AS data_confidence,
    -- Pricing / occupancy from Playtomic (NULL when no availability data)
    vpb.median_hourly_rate,
    vpb.median_peak_rate,
    vpb.median_offpeak_rate,
    vpb.median_occupancy_rate,
    vpb.median_daily_revenue_per_venue,
    vpb.price_currency
  FROM foundation.dim_cities c
  LEFT JOIN serving.venue_pricing_benchmarks vpb
    ON c.country_code = vpb.country_code
    AND c.city_slug = vpb.city_slug
  WHERE c.padel_venue_count > 0
),
scored AS (
  SELECT *,
    ROUND(
      -- Supply development (40 pts): THE maturity signal.
      -- Log-scaled density: LN(density+1)/LN(21) → 20/100k ≈ full marks.
      -- Count gate: min(1, count/5) — 1 venue=20%, 5+ venues=100%.
      -- Kills small-town inflation (1 court / 5k pop = 20/100k) without hard cutoffs.
      40.0 * LEAST(1.0, LN(COALESCE(venues_per_100k, 0) + 1) / LN(21))
           * LEAST(1.0, padel_venue_count / 5.0)
      -- Demand evidence (25 pts): occupancy when Playtomic data available.
      -- Fallback: 40% of density score (avoids double-counting with supply component).
      + 25.0 * CASE
          WHEN median_occupancy_rate IS NOT NULL
            THEN LEAST(1.0, median_occupancy_rate / 0.65)
          ELSE 0.4 * LEAST(1.0, LN(COALESCE(venues_per_100k, 0) + 1) / LN(21))
                   * LEAST(1.0, padel_venue_count / 5.0)
        END
      -- Addressable market (15 pts): population as context, not maturity signal.
      -- LN(1) = 0 so zero-pop cities score 0 here.
      + 15.0 * LEAST(1.0, LN(GREATEST(population, 1)) / LN(1000000))
      -- Economic context (10 pts): country-level income PPS.
      -- Flat per country — kept as context modifier, not primary signal.
      + 10.0 * LEAST(1.0, COALESCE(median_income_pps, 100) / 200.0)
      -- Data quality (10 pts): completeness discount.
      + 10.0 * data_confidence
    , 1)
                                 AS market_score
  FROM base
)
SELECT
  s.country_code,
  s.country_name_en,
  s.country_slug,
  s.city_name,
  s.city_slug,
  s.lat,
  s.lon,
  s.population,
  s.population_year,
  s.padel_venue_count,
  s.venues_per_100k,
  s.data_confidence,
  s.market_score,
  s.median_income_pps,
  s.income_year,
  s.median_hourly_rate,
  s.median_peak_rate,
  s.median_offpeak_rate,
  s.median_occupancy_rate,
  s.median_daily_revenue_per_venue,
  s.price_currency,
  s.geoname_id,
  CURRENT_DATE                   AS refreshed_date
FROM scored s
ORDER BY s.market_score DESC
