-- ============================================================
-- Phase 9: 全量视图参数化
-- 替换 v_store_platform_economics, v_store_category_mix, v_store_member_opportunity
-- 为按月参数化函数
-- ============================================================

-- ============================================================
-- 1. fn_store_platform_economics(p_month)
--    替换 v_store_platform_economics（无月份过滤的全量聚合）
--    数据源: bill_records, 按月份过滤 c175
-- ============================================================
CREATE OR REPLACE FUNCTION analytics.fn_store_platform_economics(p_month date)
RETURNS TABLE (
  store_code text,
  store_name text,
  meituan_received numeric,
  meituan_discount numeric,
  meituan_commission numeric,
  taobao_received numeric,
  taobao_discount numeric,
  taobao_commission numeric,
  jd_received numeric,
  jd_discount numeric,
  jd_commission numeric,
  meituan_cost_rate_pct numeric,
  taobao_cost_rate_pct numeric,
  jd_cost_rate_pct numeric
)
LANGUAGE sql
STABLE
AS $function$
  SELECT
    NULLIF(bill_records.c002, '') AS store_code,
    NULLIF(bill_records.c003, '') AS store_name,
    sum(COALESCE(NULLIF(bill_records.c151, '')::numeric, 0)) AS meituan_received,
    sum(COALESCE(NULLIF(bill_records.c101, '')::numeric, 0)) AS meituan_discount,
    sum(COALESCE(NULLIF(bill_records.c097, '')::numeric, 0)) AS meituan_commission,
    sum(COALESCE(NULLIF(bill_records.c152, '')::numeric, 0)) AS taobao_received,
    sum(COALESCE(NULLIF(bill_records.c102, '')::numeric, 0)) AS taobao_discount,
    sum(COALESCE(NULLIF(bill_records.c098, '')::numeric, 0)) AS taobao_commission,
    sum(COALESCE(NULLIF(bill_records.c150, '')::numeric, 0)) AS jd_received,
    sum(COALESCE(NULLIF(bill_records.c099, '')::numeric, 0)) AS jd_discount,
    sum(COALESCE(NULLIF(bill_records.c100, '')::numeric, 0)) AS jd_commission,
    round((sum(COALESCE(NULLIF(bill_records.c101, '')::numeric, 0)) + sum(COALESCE(NULLIF(bill_records.c097, '')::numeric, 0)))
      / NULLIF(sum(COALESCE(NULLIF(bill_records.c151, '')::numeric, 0)) + sum(COALESCE(NULLIF(bill_records.c101, '')::numeric, 0)) + sum(COALESCE(NULLIF(bill_records.c097, '')::numeric, 0)), 0) * 100, 2) AS meituan_cost_rate_pct,
    round((sum(COALESCE(NULLIF(bill_records.c102, '')::numeric, 0)) + sum(COALESCE(NULLIF(bill_records.c098, '')::numeric, 0)))
      / NULLIF(sum(COALESCE(NULLIF(bill_records.c152, '')::numeric, 0)) + sum(COALESCE(NULLIF(bill_records.c102, '')::numeric, 0)) + sum(COALESCE(NULLIF(bill_records.c098, '')::numeric, 0)), 0) * 100, 2) AS taobao_cost_rate_pct,
    round((sum(COALESCE(NULLIF(bill_records.c099, '')::numeric, 0)) + sum(COALESCE(NULLIF(bill_records.c100, '')::numeric, 0)))
      / NULLIF(sum(COALESCE(NULLIF(bill_records.c150, '')::numeric, 0)) + sum(COALESCE(NULLIF(bill_records.c099, '')::numeric, 0)) + sum(COALESCE(NULLIF(bill_records.c100, '')::numeric, 0)), 0) * 100, 2) AS jd_cost_rate_pct
  FROM bill_records
  WHERE NULLIF(bill_records.c005, '') IS NOT NULL
    AND bill_records.c175 IS NOT NULL AND bill_records.c175 != ''
    AND bill_records.c175::timestamp >= analytics.fn_month_start_ts(p_month)
    AND bill_records.c175::timestamp < analytics.fn_next_month_start_ts(p_month)
  GROUP BY NULLIF(bill_records.c002, ''), NULLIF(bill_records.c003, '');
$function$;

-- ============================================================
-- 2. fn_store_category_mix(p_month)
--    替换 v_store_category_mix（无月份过滤的全量聚合）
--    数据源: bill_records, 按月份过滤 c175
-- ============================================================
CREATE OR REPLACE FUNCTION analytics.fn_store_category_mix(p_month date)
RETURNS TABLE (
  store_code text,
  store_name text,
  consumption numeric,
  lanzhou_noodle numeric,
  western_staple numeric,
  delivery_package numeric,
  night_bbq numeric,
  cold_dishes numeric,
  silk_road_food numeric,
  noodle_share_pct numeric,
  delivery_package_share_pct numeric,
  top_category_share_pct numeric,
  top_category text
)
LANGUAGE sql
STABLE
AS $function$
  SELECT
    NULLIF(bill_records.c002, '') AS store_code,
    NULLIF(bill_records.c003, '') AS store_name,
    sum(COALESCE(NULLIF(bill_records.c009, '')::numeric, 0)) AS consumption,
    sum(COALESCE(NULLIF(bill_records.c010, '')::numeric, 0)) AS lanzhou_noodle,
    sum(COALESCE(NULLIF(bill_records.c016, '')::numeric, 0)) AS western_staple,
    sum(COALESCE(NULLIF(bill_records.c027, '')::numeric, 0)) AS delivery_package,
    sum(COALESCE(NULLIF(bill_records.c013, '')::numeric, 0)) AS night_bbq,
    sum(COALESCE(NULLIF(bill_records.c015, '')::numeric, 0)) AS cold_dishes,
    sum(COALESCE(NULLIF(bill_records.c019, '')::numeric, 0)) AS silk_road_food,
    round(sum(COALESCE(NULLIF(bill_records.c010, '')::numeric, 0))
      / NULLIF(sum(COALESCE(NULLIF(bill_records.c009, '')::numeric, 0)), 0) * 100, 2) AS noodle_share_pct,
    round(sum(COALESCE(NULLIF(bill_records.c027, '')::numeric, 0))
      / NULLIF(sum(COALESCE(NULLIF(bill_records.c009, '')::numeric, 0)), 0) * 100, 2) AS delivery_package_share_pct,
    round(GREATEST(
        sum(COALESCE(NULLIF(bill_records.c010, '')::numeric, 0)),
        sum(COALESCE(NULLIF(bill_records.c016, '')::numeric, 0)),
        sum(COALESCE(NULLIF(bill_records.c027, '')::numeric, 0)),
        sum(COALESCE(NULLIF(bill_records.c013, '')::numeric, 0)),
        sum(COALESCE(NULLIF(bill_records.c015, '')::numeric, 0)),
        sum(COALESCE(NULLIF(bill_records.c019, '')::numeric, 0))
      ) / NULLIF(sum(COALESCE(NULLIF(bill_records.c009, '')::numeric, 0)), 0) * 100, 2) AS top_category_share_pct,
    CASE GREATEST(
        sum(COALESCE(NULLIF(bill_records.c010, '')::numeric, 0)),
        sum(COALESCE(NULLIF(bill_records.c016, '')::numeric, 0)),
        sum(COALESCE(NULLIF(bill_records.c027, '')::numeric, 0)),
        sum(COALESCE(NULLIF(bill_records.c013, '')::numeric, 0)),
        sum(COALESCE(NULLIF(bill_records.c015, '')::numeric, 0)),
        sum(COALESCE(NULLIF(bill_records.c019, '')::numeric, 0))
      )
      WHEN sum(COALESCE(NULLIF(bill_records.c010, '')::numeric, 0)) THEN '兰州牛肉面'
      WHEN sum(COALESCE(NULLIF(bill_records.c016, '')::numeric, 0)) THEN '西部主食'
      WHEN sum(COALESCE(NULLIF(bill_records.c027, '')::numeric, 0)) THEN '外卖套餐'
      WHEN sum(COALESCE(NULLIF(bill_records.c013, '')::numeric, 0)) THEN '夜市烧烤'
      WHEN sum(COALESCE(NULLIF(bill_records.c015, '')::numeric, 0)) THEN '爽口凉菜'
      ELSE '丝路美食'
    END AS top_category
  FROM bill_records
  WHERE NULLIF(bill_records.c005, '') IS NOT NULL
    AND bill_records.c175 IS NOT NULL AND bill_records.c175 != ''
    AND bill_records.c175::timestamp >= analytics.fn_month_start_ts(p_month)
    AND bill_records.c175::timestamp < analytics.fn_next_month_start_ts(p_month)
  GROUP BY NULLIF(bill_records.c002, ''), NULLIF(bill_records.c003, '');
$function$;

-- ============================================================
-- 3. fn_store_member_opportunity(p_month)
--    替换 v_store_member_opportunity（无月份过滤的全量聚合）
--    数据源: analytics.bill_fact, 按月份过滤 closed_at
-- ============================================================
CREATE OR REPLACE FUNCTION analytics.fn_store_member_opportunity(p_month date)
RETURNS TABLE (
  store_code text,
  store_name text,
  bill_count bigint,
  received numeric,
  member_share_pct numeric,
  company_member_share_pct numeric,
  conversion_bill_scenario numeric,
  revenue_uplift_scenario numeric
)
LANGUAGE sql
STABLE
AS $function$
  WITH company AS (
    SELECT
      count(*) FILTER (WHERE bill_fact.member_id IS NOT NULL)::numeric / count(*)::numeric AS member_share,
      avg(bill_fact.received_total) FILTER (WHERE bill_fact.member_id IS NOT NULL) AS member_avg_bill,
      avg(bill_fact.received_total) FILTER (WHERE bill_fact.member_id IS NULL) AS nonmember_avg_bill
    FROM analytics.bill_fact
    WHERE bill_fact.closed_at >= analytics.fn_month_start_ts(p_month)
      AND bill_fact.closed_at < analytics.fn_next_month_start_ts(p_month)
  ), stores AS (
    SELECT
      bill_fact.store_code,
      bill_fact.store_name,
      count(*) AS bill_count,
      count(*) FILTER (WHERE bill_fact.member_id IS NOT NULL)::numeric / count(*)::numeric AS member_share,
      sum(bill_fact.received_total) AS received
    FROM analytics.bill_fact
    WHERE bill_fact.closed_at >= analytics.fn_month_start_ts(p_month)
      AND bill_fact.closed_at < analytics.fn_next_month_start_ts(p_month)
    GROUP BY bill_fact.store_code, bill_fact.store_name
  )
  SELECT
    s.store_code,
    s.store_name,
    s.bill_count,
    round(s.received, 2) AS received,
    round(s.member_share * 100, 2) AS member_share_pct,
    round(c.member_share * 100, 2) AS company_member_share_pct,
    round(GREATEST(c.member_share - s.member_share, 0) * s.bill_count::numeric, 0) AS conversion_bill_scenario,
    round(GREATEST(c.member_share - s.member_share, 0) * s.bill_count::numeric * (c.member_avg_bill - c.nonmember_avg_bill), 2) AS revenue_uplift_scenario
  FROM stores s
  CROSS JOIN company c;
$function$;
