-- Materialized aggregates for fast UI queries.
-- Refresh strategy: REFRESH MATERIALIZED VIEW CONCURRENTLY after each new quarter load.

-- 1. Per cadastral quarter × period × doc_type × area_bucket
DROP MATERIALIZED VIEW IF EXISTS rr_agg_cad_quarter CASCADE;
CREATE MATERIALIZED VIEW rr_agg_cad_quarter AS
SELECT
    region_code,
    quarter_cad_number,
    period_start_date,
    doc_type,
    -- area bucket inspired by NSPD MarketAnalytics filter
    CASE
        WHEN area < 25  THEN 'lt25'
        WHEN area < 40  THEN '25-40'
        WHEN area < 60  THEN '40-60'
        WHEN area < 90  THEN '60-90'
        WHEN area < 150 THEN '90-150'
        ELSE 'gt150'
    END AS area_bucket,
    SUM(deal_count)                                              AS deals_count,
    COUNT(*)                                                     AS rows_count,
    SUM(deal_count * area)                                       AS total_area_sqm,
    SUM(deal_count * deal_price)                                 AS total_value_rub,
    percentile_cont(0.10) WITHIN GROUP (ORDER BY price_per_sqm)  AS p10_price_sqm,
    percentile_cont(0.50) WITHIN GROUP (ORDER BY price_per_sqm)  AS median_price_sqm,
    percentile_cont(0.90) WITHIN GROUP (ORDER BY price_per_sqm)  AS p90_price_sqm,
    AVG(price_per_sqm)                                           AS mean_price_sqm,
    MIN(price_per_sqm)                                           AS min_price_sqm,
    MAX(price_per_sqm)                                           AS max_price_sqm
FROM rosreestr_deals
WHERE area BETWEEN 5 AND 1000
  AND deal_price BETWEEN 100000 AND 1e10        -- discard outliers (typos, junk in source)
  AND realestate_type_code IN ('002001003000')  -- помещения (квартиры). Здания/ЗУ — отдельный rollup
GROUP BY region_code, quarter_cad_number, period_start_date, doc_type,
         CASE WHEN area<25 THEN 'lt25' WHEN area<40 THEN '25-40' WHEN area<60 THEN '40-60'
              WHEN area<90 THEN '60-90' WHEN area<150 THEN '90-150' ELSE 'gt150' END
WITH NO DATA;

CREATE UNIQUE INDEX rr_agg_cq_pk ON rr_agg_cad_quarter
    (region_code, quarter_cad_number, period_start_date, doc_type, area_bucket);
CREATE INDEX rr_agg_cq_period_idx ON rr_agg_cad_quarter (period_start_date);
CREATE INDEX rr_agg_cq_region_period_idx ON rr_agg_cad_quarter (region_code, period_start_date);

-- 2. Per region × period × doc_type — для регионального обзора (Урал dashboard)
DROP MATERIALIZED VIEW IF EXISTS rr_agg_region CASCADE;
CREATE MATERIALIZED VIEW rr_agg_region AS
SELECT
    region_code,
    period_start_date,
    doc_type,
    realestate_type_code,
    SUM(deal_count)                                              AS deals_count,
    COUNT(*)                                                     AS rows_count,
    SUM(deal_count * area)                                       AS total_area_sqm,
    SUM(deal_count * deal_price)                                 AS total_value_rub,
    percentile_cont(0.10) WITHIN GROUP (ORDER BY price_per_sqm)  AS p10_price_sqm,
    percentile_cont(0.50) WITHIN GROUP (ORDER BY price_per_sqm)  AS median_price_sqm,
    percentile_cont(0.90) WITHIN GROUP (ORDER BY price_per_sqm)  AS p90_price_sqm
FROM rosreestr_deals
WHERE area BETWEEN 5 AND 1000
  AND deal_price BETWEEN 100000 AND 1e10
GROUP BY region_code, period_start_date, doc_type, realestate_type_code
WITH NO DATA;

CREATE UNIQUE INDEX rr_agg_region_pk ON rr_agg_region
    (region_code, period_start_date, doc_type, realestate_type_code);

-- 3. Per city/settlement (для дашборда Екатеринбург)
DROP MATERIALIZED VIEW IF EXISTS rr_agg_settlement CASCADE;
CREATE MATERIALIZED VIEW rr_agg_settlement AS
SELECT
    region_code,
    COALESCE(city, district) AS settlement_name,
    period_start_date,
    doc_type,
    realestate_type_code,
    SUM(deal_count)                                              AS deals_count,
    SUM(deal_count * area)                                       AS total_area_sqm,
    percentile_cont(0.50) WITHIN GROUP (ORDER BY price_per_sqm)  AS median_price_sqm,
    percentile_cont(0.10) WITHIN GROUP (ORDER BY price_per_sqm)  AS p10_price_sqm,
    percentile_cont(0.90) WITHIN GROUP (ORDER BY price_per_sqm)  AS p90_price_sqm,
    COUNT(DISTINCT quarter_cad_number)                           AS distinct_cad_quarters
FROM rosreestr_deals
WHERE area BETWEEN 5 AND 1000
  AND deal_price BETWEEN 100000 AND 1e10
  AND COALESCE(city, district) IS NOT NULL
GROUP BY region_code, COALESCE(city, district), period_start_date, doc_type, realestate_type_code
WITH NO DATA;

CREATE UNIQUE INDEX rr_agg_settl_pk ON rr_agg_settlement
    (region_code, settlement_name, period_start_date, doc_type, realestate_type_code);
CREATE INDEX rr_agg_settl_search ON rr_agg_settlement (region_code, settlement_name);

-- Initial fill
REFRESH MATERIALIZED VIEW rr_agg_cad_quarter;
REFRESH MATERIALIZED VIEW rr_agg_region;
REFRESH MATERIALIZED VIEW rr_agg_settlement;
