-- ============================================
-- 数据分析模块数据库 Schema（Supabase/Postgres）
-- ============================================
-- 用途：创建 analytics_* 表、索引、RLS策略、RPC函数
-- 参考：`docs/ANALYTICS_DB_DESIGN.md`
-- 
-- 执行顺序：
--   1. 先执行基础业务表（`01_create_tables.sql`）
--   2. 再执行本文档（`ANALYTICS_DB_SCHEMA.sql`）
--   3. 最后执行 `ANALYTICS_TEST_SEED.sql` 插入测试数据（受 RLS 影响，需较高权限执行）
-- ============================================

-- ============================================
-- 1. Analytics 表结构
-- ============================================

-- 说明：
-- - 本目录（pages/mall/analytics/test）中的基础表结构由 01_create_tables.sql 提供。
-- - 本文件只负责 analytics_* 表 + RLS + RPC。

-- 1.1 分析师偏好设置
CREATE TABLE IF NOT EXISTS analytics_user_preferences (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  default_period TEXT NOT NULL DEFAULT '7d',
  timezone TEXT DEFAULT 'Asia/Shanghai',
  currency TEXT DEFAULT 'CNY',
  kpi_cards JSONB DEFAULT '[]'::jsonb,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW(),
  UNIQUE(user_id)
);

-- 中文注释
COMMENT ON TABLE public.analytics_user_preferences IS '分析师偏好设置表';
COMMENT ON COLUMN public.analytics_user_preferences.id IS '主键';
COMMENT ON COLUMN public.analytics_user_preferences.user_id IS '用户ID（关联 users.id / 建议与 auth.uid 对齐）';
COMMENT ON COLUMN public.analytics_user_preferences.default_period IS '默认统计周期（如 7d/30d/90d/1y）';
COMMENT ON COLUMN public.analytics_user_preferences.timezone IS '时区（默认 Asia/Shanghai）';
COMMENT ON COLUMN public.analytics_user_preferences.currency IS '币种（默认 CNY）';
COMMENT ON COLUMN public.analytics_user_preferences.kpi_cards IS 'KPI 卡片配置（JSON 数组）';
COMMENT ON COLUMN public.analytics_user_preferences.created_at IS '创建时间';
COMMENT ON COLUMN public.analytics_user_preferences.updated_at IS '更新时间';

-- 1.2 报表定义
CREATE TABLE IF NOT EXISTS analytics_reports (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  owner_user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  merchant_id UUID REFERENCES merchants(id) ON DELETE SET NULL,
  title TEXT NOT NULL,
  description TEXT DEFAULT '',
  type TEXT NOT NULL, -- sales/users/orders/conversion/coupon/delivery/market/custom
  period TEXT NOT NULL, -- 7d/30d/90d/1y
  date_start DATE,
  date_end DATE,
  status TEXT NOT NULL DEFAULT 'ready', -- pending/ready/failed/scheduled/shared
  generated_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- 中文注释
COMMENT ON TABLE public.analytics_reports IS '分析报表表（报表定义/实例）';
COMMENT ON COLUMN public.analytics_reports.id IS '报表ID';
COMMENT ON COLUMN public.analytics_reports.owner_user_id IS '报表所属用户ID（创建者）';
COMMENT ON COLUMN public.analytics_reports.merchant_id IS '商家ID（可空：表示全站/不限定商家）';
COMMENT ON COLUMN public.analytics_reports.title IS '报表标题';
COMMENT ON COLUMN public.analytics_reports.description IS '报表描述';
COMMENT ON COLUMN public.analytics_reports.type IS '报表类型（sales/users/orders/conversion 等）';
COMMENT ON COLUMN public.analytics_reports.period IS '统计周期（7d/30d/90d/1y 或自定义）';
COMMENT ON COLUMN public.analytics_reports.date_start IS '自定义开始日期（可空）';
COMMENT ON COLUMN public.analytics_reports.date_end IS '自定义结束日期（可空）';
COMMENT ON COLUMN public.analytics_reports.status IS '状态（pending/ready/failed/scheduled/shared）';
COMMENT ON COLUMN public.analytics_reports.generated_at IS '生成时间';
COMMENT ON COLUMN public.analytics_reports.created_at IS '创建时间';
COMMENT ON COLUMN public.analytics_reports.updated_at IS '更新时间';

-- 1.3 报表核心指标
CREATE TABLE IF NOT EXISTS analytics_report_metrics (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  report_id UUID NOT NULL REFERENCES analytics_reports(id) ON DELETE CASCADE,
  metric_key TEXT NOT NULL,
  metric_label TEXT NOT NULL,
  metric_value_num NUMERIC,
  metric_value_text TEXT,
  format TEXT NOT NULL DEFAULT 'number', -- number/currency/percent
  change_pct NUMERIC DEFAULT 0,
  icon TEXT DEFAULT '',
  color TEXT DEFAULT '#3b82f6',
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- 中文注释
COMMENT ON TABLE public.analytics_report_metrics IS '报表核心指标表';
COMMENT ON COLUMN public.analytics_report_metrics.id IS '主键';
COMMENT ON COLUMN public.analytics_report_metrics.report_id IS '所属报表ID';
COMMENT ON COLUMN public.analytics_report_metrics.metric_key IS '指标Key（如 gmv/orders/conversion_rate）';
COMMENT ON COLUMN public.analytics_report_metrics.metric_label IS '指标名称（展示用）';
COMMENT ON COLUMN public.analytics_report_metrics.metric_value_num IS '指标数值（数值型）';
COMMENT ON COLUMN public.analytics_report_metrics.metric_value_text IS '指标文本（已格式化，如百分比字符串）';
COMMENT ON COLUMN public.analytics_report_metrics.format IS '展示格式（number/currency/percent）';
COMMENT ON COLUMN public.analytics_report_metrics.change_pct IS '变化百分比（环比/同比，单位：%）';
COMMENT ON COLUMN public.analytics_report_metrics.icon IS '图标（可选，建议使用纯文本 key）';
COMMENT ON COLUMN public.analytics_report_metrics.color IS '颜色（UI 展示用）';
COMMENT ON COLUMN public.analytics_report_metrics.created_at IS '创建时间';

-- 1.4 报表明细行（趋势数据）
CREATE TABLE IF NOT EXISTS analytics_report_rows (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  report_id UUID NOT NULL REFERENCES analytics_reports(id) ON DELETE CASCADE,
  row_date DATE NOT NULL,
  gmv NUMERIC DEFAULT 0,
  orders INTEGER DEFAULT 0,
  users INTEGER DEFAULT 0,
  conversion NUMERIC DEFAULT 0,
  avg_order_amount NUMERIC DEFAULT 0,
  extra JSONB DEFAULT '{}'::jsonb,
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- 中文注释
COMMENT ON TABLE public.analytics_report_rows IS '报表明细行表（趋势数据）';
COMMENT ON COLUMN public.analytics_report_rows.id IS '主键';
COMMENT ON COLUMN public.analytics_report_rows.report_id IS '所属报表ID';
COMMENT ON COLUMN public.analytics_report_rows.row_date IS '统计日期';
COMMENT ON COLUMN public.analytics_report_rows.gmv IS 'GMV（元）';
COMMENT ON COLUMN public.analytics_report_rows.orders IS '订单数';
COMMENT ON COLUMN public.analytics_report_rows.users IS '用户数（可选）';
COMMENT ON COLUMN public.analytics_report_rows.conversion IS '转化率（0-100）';
COMMENT ON COLUMN public.analytics_report_rows.avg_order_amount IS '客单价';
COMMENT ON COLUMN public.analytics_report_rows.extra IS '扩展字段（用于自定义报表列）';
COMMENT ON COLUMN public.analytics_report_rows.created_at IS '创建时间';

-- 1.5 数据洞察
CREATE TABLE IF NOT EXISTS analytics_insights (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  report_id UUID REFERENCES analytics_reports(id) ON DELETE CASCADE,
  owner_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
  type TEXT NOT NULL, -- positive/warning/negative/info
  impact TEXT NOT NULL DEFAULT 'medium', -- high/medium/low
  title TEXT NOT NULL,
  content TEXT NOT NULL,
  tags TEXT[] DEFAULT '{}',
  created_at TIMESTAMPTZ DEFAULT NOW()
);

-- 中文注释
COMMENT ON TABLE public.analytics_insights IS '数据洞察表（建议/预警/提示）';
COMMENT ON COLUMN public.analytics_insights.id IS '洞察ID';
COMMENT ON COLUMN public.analytics_insights.report_id IS '关联报表ID（可空）';
COMMENT ON COLUMN public.analytics_insights.owner_user_id IS '所属用户ID（可空：系统生成）';
COMMENT ON COLUMN public.analytics_insights.type IS '洞察类型（positive/warning/negative/info）';
COMMENT ON COLUMN public.analytics_insights.impact IS '影响等级（high/medium/low）';
COMMENT ON COLUMN public.analytics_insights.title IS '洞察标题';
COMMENT ON COLUMN public.analytics_insights.content IS '洞察内容';
COMMENT ON COLUMN public.analytics_insights.tags IS '标签数组';
COMMENT ON COLUMN public.analytics_insights.created_at IS '创建时间';

-- 1.6 报表收藏
CREATE TABLE IF NOT EXISTS analytics_report_favorites (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  report_id UUID NOT NULL REFERENCES analytics_reports(id) ON DELETE CASCADE,
  created_at TIMESTAMPTZ DEFAULT NOW(),
  UNIQUE(user_id, report_id)
);

-- 中文注释
COMMENT ON TABLE public.analytics_report_favorites IS '报表收藏表';
COMMENT ON COLUMN public.analytics_report_favorites.id IS '主键';
COMMENT ON COLUMN public.analytics_report_favorites.user_id IS '用户ID';
COMMENT ON COLUMN public.analytics_report_favorites.report_id IS '报表ID';
COMMENT ON COLUMN public.analytics_report_favorites.created_at IS '创建时间';

-- 1.7 导出任务
CREATE TABLE IF NOT EXISTS analytics_export_jobs (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  report_id UUID NOT NULL REFERENCES analytics_reports(id) ON DELETE CASCADE,
  format TEXT NOT NULL, -- csv/xlsx/pdf/json
  status TEXT NOT NULL DEFAULT 'queued', -- queued/running/done/failed
  file_path TEXT,
  error_message TEXT DEFAULT '',
  created_at TIMESTAMPTZ DEFAULT NOW(),
  finished_at TIMESTAMPTZ
);

-- 中文注释
COMMENT ON TABLE public.analytics_export_jobs IS '导出任务表（导出历史/队列）';
COMMENT ON COLUMN public.analytics_export_jobs.id IS '导出任务ID';
COMMENT ON COLUMN public.analytics_export_jobs.user_id IS '发起用户ID';
COMMENT ON COLUMN public.analytics_export_jobs.report_id IS '关联报表ID';
COMMENT ON COLUMN public.analytics_export_jobs.format IS '导出格式（csv/xlsx/pdf/json）';
COMMENT ON COLUMN public.analytics_export_jobs.status IS '任务状态（queued/running/done/failed）';
COMMENT ON COLUMN public.analytics_export_jobs.file_path IS '文件路径（Storage 路径，可空）';
COMMENT ON COLUMN public.analytics_export_jobs.error_message IS '失败原因（可空）';
COMMENT ON COLUMN public.analytics_export_jobs.created_at IS '创建时间';
COMMENT ON COLUMN public.analytics_export_jobs.finished_at IS '完成时间（可空）';

-- ============================================
-- 2. 索引
-- ============================================

-- analytics_reports
CREATE INDEX IF NOT EXISTS idx_analytics_reports_owner_created ON analytics_reports(owner_user_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_analytics_reports_type_generated ON analytics_reports(type, generated_at DESC);
CREATE INDEX IF NOT EXISTS idx_analytics_reports_status ON analytics_reports(status);

-- analytics_report_metrics
CREATE INDEX IF NOT EXISTS idx_analytics_report_metrics_report ON analytics_report_metrics(report_id, metric_key);

-- analytics_report_rows
CREATE INDEX IF NOT EXISTS idx_analytics_report_rows_report_date ON analytics_report_rows(report_id, row_date);

-- analytics_insights
CREATE INDEX IF NOT EXISTS idx_analytics_insights_created ON analytics_insights(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_analytics_insights_report ON analytics_insights(report_id, created_at DESC);

-- analytics_export_jobs
CREATE INDEX IF NOT EXISTS idx_analytics_export_jobs_user ON analytics_export_jobs(user_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_analytics_export_jobs_status ON analytics_export_jobs(status);

-- ============================================
-- 3. RLS（Row Level Security）策略
-- ============================================

-- 启用 RLS
ALTER TABLE analytics_user_preferences ENABLE ROW LEVEL SECURITY;
ALTER TABLE analytics_reports ENABLE ROW LEVEL SECURITY;
ALTER TABLE analytics_report_metrics ENABLE ROW LEVEL SECURITY;
ALTER TABLE analytics_report_rows ENABLE ROW LEVEL SECURITY;
ALTER TABLE analytics_insights ENABLE ROW LEVEL SECURITY;
ALTER TABLE analytics_report_favorites ENABLE ROW LEVEL SECURITY;
ALTER TABLE analytics_export_jobs ENABLE ROW LEVEL SECURITY;

-- analytics_user_preferences: 用户只能访问自己的偏好
DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_user_preferences' AND policyname='Users can view own preferences') THEN
    EXECUTE 'CREATE POLICY "Users can view own preferences" ON public.analytics_user_preferences FOR SELECT USING (auth.uid() = user_id)';
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_user_preferences' AND policyname='Users can insert own preferences') THEN
    EXECUTE 'CREATE POLICY "Users can insert own preferences" ON public.analytics_user_preferences FOR INSERT WITH CHECK (auth.uid() = user_id)';
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_user_preferences' AND policyname='Users can update own preferences') THEN
    EXECUTE 'CREATE POLICY "Users can update own preferences" ON public.analytics_user_preferences FOR UPDATE USING (auth.uid() = user_id)';
  END IF;
END $$;

-- analytics_reports: 用户可访问自己创建的报表和共享报表
DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_reports' AND policyname='Users can view own reports') THEN
    EXECUTE 'CREATE POLICY "Users can view own reports" ON public.analytics_reports FOR SELECT USING (auth.uid() = owner_user_id OR status = ''shared'')';
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_reports' AND policyname='Users can insert own reports') THEN
    EXECUTE 'CREATE POLICY "Users can insert own reports" ON public.analytics_reports FOR INSERT WITH CHECK (auth.uid() = owner_user_id)';
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_reports' AND policyname='Users can update own reports') THEN
    EXECUTE 'CREATE POLICY "Users can update own reports" ON public.analytics_reports FOR UPDATE USING (auth.uid() = owner_user_id)';
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_reports' AND policyname='Users can delete own reports') THEN
    EXECUTE 'CREATE POLICY "Users can delete own reports" ON public.analytics_reports FOR DELETE USING (auth.uid() = owner_user_id)';
  END IF;
END $$;

-- analytics_report_metrics: 通过 report_id 关联权限
DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_report_metrics' AND policyname='Users can view metrics of accessible reports') THEN
    EXECUTE 'CREATE POLICY "Users can view metrics of accessible reports" ON public.analytics_report_metrics FOR SELECT USING (EXISTS (SELECT 1 FROM public.analytics_reports WHERE public.analytics_reports.id = public.analytics_report_metrics.report_id AND (public.analytics_reports.owner_user_id = auth.uid() OR public.analytics_reports.status = ''shared'')))';
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_report_metrics' AND policyname='Users can manage metrics of own reports') THEN
    EXECUTE 'CREATE POLICY "Users can manage metrics of own reports" ON public.analytics_report_metrics FOR ALL USING (EXISTS (SELECT 1 FROM public.analytics_reports WHERE public.analytics_reports.id = public.analytics_report_metrics.report_id AND public.analytics_reports.owner_user_id = auth.uid()))';
  END IF;
END $$;

-- analytics_report_rows: 通过 report_id 关联权限
DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_report_rows' AND policyname='Users can view rows of accessible reports') THEN
    EXECUTE 'CREATE POLICY "Users can view rows of accessible reports" ON public.analytics_report_rows FOR SELECT USING (EXISTS (SELECT 1 FROM public.analytics_reports WHERE public.analytics_reports.id = public.analytics_report_rows.report_id AND (public.analytics_reports.owner_user_id = auth.uid() OR public.analytics_reports.status = ''shared'')))';
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_report_rows' AND policyname='Users can manage rows of own reports') THEN
    EXECUTE 'CREATE POLICY "Users can manage rows of own reports" ON public.analytics_report_rows FOR ALL USING (EXISTS (SELECT 1 FROM public.analytics_reports WHERE public.analytics_reports.id = public.analytics_report_rows.report_id AND public.analytics_reports.owner_user_id = auth.uid()))';
  END IF;
END $$;

-- analytics_insights: 通过 report_id 或 owner_user_id 关联权限
DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_insights' AND policyname='Users can view accessible insights') THEN
    EXECUTE 'CREATE POLICY "Users can view accessible insights" ON public.analytics_insights FOR SELECT USING (owner_user_id = auth.uid() OR (report_id IS NOT NULL AND EXISTS (SELECT 1 FROM public.analytics_reports WHERE public.analytics_reports.id = public.analytics_insights.report_id AND (public.analytics_reports.owner_user_id = auth.uid() OR public.analytics_reports.status = ''shared''))))';
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_insights' AND policyname='Users can manage own insights') THEN
    EXECUTE 'CREATE POLICY "Users can manage own insights" ON public.analytics_insights FOR ALL USING (owner_user_id = auth.uid())';
  END IF;
END $$;

-- analytics_report_favorites: 用户只能访问自己的收藏
DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_report_favorites' AND policyname='Users can manage own favorites') THEN
    EXECUTE 'CREATE POLICY "Users can manage own favorites" ON public.analytics_report_favorites FOR ALL USING (auth.uid() = user_id)';
  END IF;
END $$;

-- analytics_export_jobs: 用户只能访问自己的导出任务
DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_policies WHERE schemaname='public' AND tablename='analytics_export_jobs' AND policyname='Users can manage own export jobs') THEN
    EXECUTE 'CREATE POLICY "Users can manage own export jobs" ON public.analytics_export_jobs FOR ALL USING (auth.uid() = user_id)';
  END IF;
END $$;

-- ============================================
-- 4. RPC 函数（Postgres Functions）
-- ============================================

-- 4.1 实时 KPI 计算函数
CREATE OR REPLACE FUNCTION rpc_analytics_realtime_kpis(
  p_start TIMESTAMPTZ,
  p_end TIMESTAMPTZ,
  p_compare_start TIMESTAMPTZ,
  p_compare_end TIMESTAMPTZ,
  p_merchant_id UUID DEFAULT NULL
)
RETURNS TABLE (
  gmv NUMERIC,
  gmv_growth NUMERIC,
  orders INTEGER,
  order_growth NUMERIC,
  online_users INTEGER,
  conversion_rate NUMERIC,
  conversion_growth NUMERIC
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
  v_gmv NUMERIC := 0;
  v_gmv_compare NUMERIC := 0;
  v_orders INTEGER := 0;
  v_orders_compare INTEGER := 0;
  v_online_users INTEGER := 0;
  v_order_users INTEGER := 0;
  v_visitors INTEGER := 0;
  v_visitors_compare INTEGER := 0;
  v_order_users_compare INTEGER := 0;
BEGIN
  IF auth.uid() IS NULL THEN
    RAISE EXCEPTION 'unauthorized';
  END IF;

  -- 计算当前时间段 GMV 和订单数
  SELECT 
    COALESCE(SUM(total_amount), 0),
    COUNT(*)
  INTO v_gmv, v_orders
  FROM orders
  WHERE created_at >= p_start
    AND created_at < p_end
    AND status = 2 -- 已支付
    AND (p_merchant_id IS NULL OR merchant_id = p_merchant_id);
  
  -- 计算对比时间段 GMV 和订单数
  SELECT 
    COALESCE(SUM(total_amount), 0),
    COUNT(*)
  INTO v_gmv_compare, v_orders_compare
  FROM orders
  WHERE created_at >= p_compare_start
    AND created_at < p_compare_end
    AND status = 2 -- 已支付
    AND (p_merchant_id IS NULL OR merchant_id = p_merchant_id);
  
  -- 计算在线用户（最近5分钟活跃）
  SELECT COUNT(DISTINCT user_id)
  INTO v_online_users
  FROM user_sessions
  WHERE last_active_at >= (NOW() - INTERVAL '5 minutes')
    AND is_active = true;
  
  -- 计算当前时间段下单用户数
  SELECT COUNT(DISTINCT user_id)
  INTO v_order_users
  FROM orders
  WHERE created_at >= p_start
    AND created_at < p_end
    AND status = 2
    AND (p_merchant_id IS NULL OR merchant_id = p_merchant_id);
  
  -- 计算当前时间段访问用户数
  SELECT COUNT(DISTINCT user_id)
  INTO v_visitors
  FROM user_sessions
  WHERE created_at >= p_start
    AND created_at < p_end;
  
  -- 计算对比时间段访问用户数和下单用户数
  SELECT 
    COUNT(DISTINCT user_id),
    (SELECT COUNT(DISTINCT user_id) FROM orders 
     WHERE created_at >= p_compare_start AND created_at < p_compare_end 
     AND status = 2 AND (p_merchant_id IS NULL OR merchant_id = p_merchant_id))
  INTO v_visitors_compare, v_order_users_compare
  FROM user_sessions
  WHERE created_at >= p_compare_start
    AND created_at < p_compare_end;
  
  -- 返回结果
  RETURN QUERY SELECT
    v_gmv,
    CASE WHEN v_gmv_compare > 0 THEN ((v_gmv - v_gmv_compare) / v_gmv_compare * 100) ELSE (CASE WHEN v_gmv > 0 THEN 100 ELSE 0 END) END,
    v_orders,
    CASE WHEN v_orders_compare > 0 THEN ((v_orders - v_orders_compare)::NUMERIC / v_orders_compare * 100) ELSE (CASE WHEN v_orders > 0 THEN 100 ELSE 0 END) END,
    COALESCE(v_online_users, 0),
    CASE WHEN v_visitors > 0 THEN (v_order_users::NUMERIC / v_visitors * 100) ELSE 0 END,
    CASE WHEN v_visitors_compare > 0 AND v_order_users_compare > 0 THEN 
      (((v_order_users::NUMERIC / NULLIF(v_visitors, 0)) - (v_order_users_compare::NUMERIC / NULLIF(v_visitors_compare, 0))) / (v_order_users_compare::NUMERIC / NULLIF(v_visitors_compare, 0)) * 100)
    ELSE 0 END;
END;
$$;

-- 4.2 趋势数据查询函数（按日期聚合）
CREATE OR REPLACE FUNCTION rpc_analytics_trend_data(
  p_start_date DATE,
  p_end_date DATE,
  p_merchant_id UUID DEFAULT NULL
)
RETURNS TABLE (
  date DATE,
  gmv NUMERIC,
  orders INTEGER,
  users INTEGER
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
BEGIN
  IF auth.uid() IS NULL THEN
    RAISE EXCEPTION 'unauthorized';
  END IF;

  RETURN QUERY
  SELECT 
    DATE(o.created_at) AS date,
    COALESCE(SUM(o.total_amount), 0) AS gmv,
    COUNT(*)::INTEGER AS orders,
    COUNT(DISTINCT o.user_id)::INTEGER AS users
  FROM orders o
  WHERE DATE(o.created_at) >= p_start_date
    AND DATE(o.created_at) <= p_end_date
    AND o.status = 2 -- 已支付
    AND (p_merchant_id IS NULL OR o.merchant_id = p_merchant_id)
  GROUP BY DATE(o.created_at)
  ORDER BY date;
END;
$$;

-- 4.3 热销商品 TOP（按 GMV）
CREATE OR REPLACE FUNCTION rpc_analytics_top_products(
  p_start_date DATE,
  p_end_date DATE,
  p_limit INTEGER DEFAULT 10,
  p_merchant_id UUID DEFAULT NULL
)
RETURNS TABLE (
  id UUID,
  name TEXT,
  sales NUMERIC
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
BEGIN
  IF auth.uid() IS NULL THEN
    RAISE EXCEPTION 'unauthorized';
  END IF;

  RETURN QUERY
  SELECT
    p.id,
    CAST(p.name AS TEXT) AS name,
    CAST(COALESCE(SUM(oi.total_amount), 0) AS NUMERIC) AS sales
  FROM order_items oi
  JOIN orders o ON o.id = oi.order_id
  JOIN products p ON p.id = oi.product_id
  WHERE DATE(o.created_at) >= p_start_date
    AND DATE(o.created_at) <= p_end_date
    AND o.status = 2
    AND (p_merchant_id IS NULL OR o.merchant_id = p_merchant_id)
  GROUP BY p.id, p.name
  ORDER BY sales DESC
  LIMIT p_limit;
END;
$$;

-- 4.4 商家 TOP（按 GMV）
CREATE OR REPLACE FUNCTION rpc_analytics_top_merchants(
  p_start_date DATE,
  p_end_date DATE,
  p_limit INTEGER DEFAULT 10
)
RETURNS TABLE (
  id UUID,
  name TEXT,
  sales NUMERIC,
  growth NUMERIC
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
  v_days INTEGER := GREATEST(1, (p_end_date - p_start_date + 1));
  v_prev_start DATE := p_start_date - v_days;
  v_prev_end DATE := p_start_date - 1;
BEGIN
  IF auth.uid() IS NULL THEN
    RAISE EXCEPTION 'unauthorized';
  END IF;

  RETURN QUERY
  WITH cur AS (
    SELECT
      m.id AS merchant_id,
      CAST(COALESCE(m.shop_name, '未知商家') AS TEXT) AS name,
      CAST(COALESCE(SUM(o.total_amount), 0) AS NUMERIC) AS sales
    FROM merchants m
    LEFT JOIN orders o ON o.merchant_id = m.id
      AND DATE(o.created_at) >= p_start_date
      AND DATE(o.created_at) <= p_end_date
      AND o.status = 2
    GROUP BY m.id, m.shop_name
  ),
  prev AS (
    SELECT
      m.id AS merchant_id,
      CAST(COALESCE(SUM(o.total_amount), 0) AS NUMERIC) AS sales
    FROM merchants m
    LEFT JOIN orders o ON o.merchant_id = m.id
      AND DATE(o.created_at) >= v_prev_start
      AND DATE(o.created_at) <= v_prev_end
      AND o.status = 2
    GROUP BY m.id
  )
  SELECT
    CAST(cur.merchant_id AS UUID) AS id,
    CAST(cur.name AS TEXT) AS name,
    CAST(cur.sales AS NUMERIC) AS sales,
    CAST(
      CASE
        WHEN COALESCE(prev.sales, 0) > 0 THEN ((cur.sales - prev.sales) / prev.sales * 100)
        WHEN cur.sales > 0 THEN 100
        ELSE 0
      END AS NUMERIC
    ) AS growth
  FROM cur
  LEFT JOIN prev ON prev.merchant_id = cur.merchant_id
  ORDER BY cur.sales DESC
  LIMIT p_limit;
END;
$$;

-- 4.5 用户结构（分群：未消费/消费一次/留存客户/回流客户）
CREATE OR REPLACE FUNCTION rpc_analytics_user_segments(
  p_start_date DATE,
  p_end_date DATE
)
RETURNS TABLE (
  name TEXT,
  value INTEGER
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
BEGIN
  IF auth.uid() IS NULL THEN
    RAISE EXCEPTION 'unauthorized';
  END IF;

  RETURN QUERY
  WITH u AS (
    SELECT id AS user_id FROM users
  ),
  cur_orders AS (
    SELECT user_id, COUNT(*) AS cnt
    FROM orders
    WHERE DATE(created_at) >= p_start_date
      AND DATE(created_at) <= p_end_date
      AND status = 2
    GROUP BY user_id
  ),
  has_before AS (
    SELECT user_id, 1 AS has_before
    FROM orders
    WHERE DATE(created_at) < p_start_date
      AND status = 2
    GROUP BY user_id
  ),
  cls AS (
    SELECT
      u.user_id,
      COALESCE(c.cnt, 0) AS cur_cnt,
      COALESCE(b.has_before, 0) AS before_flag
    FROM u
    LEFT JOIN cur_orders c ON c.user_id = u.user_id
    LEFT JOIN has_before b ON b.user_id = u.user_id
  )
  SELECT CAST('未消费用户' AS TEXT) AS name, CAST(COUNT(*) AS INTEGER) AS value FROM cls WHERE cur_cnt = 0
  UNION ALL
  SELECT CAST('消费一次用户' AS TEXT) AS name, CAST(COUNT(*) AS INTEGER) AS value FROM cls WHERE cur_cnt = 1
  UNION ALL
  SELECT CAST('留存客户' AS TEXT) AS name, CAST(COUNT(*) AS INTEGER) AS value FROM cls WHERE cur_cnt >= 2
  UNION ALL
  SELECT CAST('回流客户' AS TEXT) AS name, CAST(COUNT(*) AS INTEGER) AS value FROM cls WHERE cur_cnt >= 1 AND before_flag = 1;
END;
$$;

-- 4.6 流量来源（基于 page_views.source）
CREATE OR REPLACE FUNCTION rpc_analytics_traffic_sources(
  p_start_date DATE,
  p_end_date DATE
)
RETURNS TABLE (
  name TEXT,
  value INTEGER
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
BEGIN
  IF auth.uid() IS NULL THEN
    RAISE EXCEPTION 'unauthorized';
  END IF;

  RETURN QUERY
  SELECT
    CAST(
      CASE
        WHEN source = 'direct' THEN '直接访问'
        WHEN source = 'search' THEN '搜索引擎'
        WHEN source = 'social' THEN '社交媒体'
        WHEN source = 'ad' THEN '广告推广'
        ELSE COALESCE(source, '未知')
      END AS TEXT
    ) AS name,
    CAST(COUNT(*) AS INTEGER) AS value
  FROM page_views
  WHERE DATE(created_at) >= p_start_date
    AND DATE(created_at) <= p_end_date
  GROUP BY 1
  ORDER BY value DESC;
END;
$$;

-- 4.7 用户分析 KPI（总用户/新用户/活跃/复购率 等）
-- 说明：指标口径为“占总用户数的百分比”，增长为与上一周期对比的百分比变化。
CREATE OR REPLACE FUNCTION rpc_analytics_user_kpis(
  p_start_date DATE,
  p_end_date DATE
)
RETURNS TABLE (
  total_users INTEGER,
  user_growth NUMERIC,
  new_users INTEGER,
  new_user_growth NUMERIC,
  active_rate NUMERIC,
  active_growth NUMERIC,
  repurchase_rate NUMERIC,
  repurchase_growth NUMERIC
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
  v_days INTEGER := GREATEST(1, (p_end_date - p_start_date + 1));
  v_prev_start DATE := p_start_date - v_days;
  v_prev_end DATE := p_start_date - 1;

  v_total INTEGER := 0;
  v_new INTEGER := 0;
  v_prev_new INTEGER := 0;

  v_active INTEGER := 0;
  v_prev_active INTEGER := 0;

  v_repurchase INTEGER := 0;
  v_prev_repurchase INTEGER := 0;
BEGIN
  IF auth.uid() IS NULL THEN
    RAISE EXCEPTION 'unauthorized';
  END IF;

  -- 总用户数（统计兼容表）
  SELECT COUNT(*)::INTEGER INTO v_total FROM public.users;

  -- 新用户：按 users.created_at 的日期口径
  SELECT COUNT(*)::INTEGER INTO v_new
  FROM public.users
  WHERE DATE(created_at) >= p_start_date AND DATE(created_at) <= p_end_date;

  SELECT COUNT(*)::INTEGER INTO v_prev_new
  FROM public.users
  WHERE DATE(created_at) >= v_prev_start AND DATE(created_at) <= v_prev_end;

  -- 活跃用户：最近活跃时间落在周期内的去重 user_id（会话表）
  SELECT COUNT(DISTINCT user_id)::INTEGER INTO v_active
  FROM public.user_sessions
  WHERE DATE(last_active_at) >= p_start_date AND DATE(last_active_at) <= p_end_date
    AND is_active = true;

  SELECT COUNT(DISTINCT user_id)::INTEGER INTO v_prev_active
  FROM public.user_sessions
  WHERE DATE(last_active_at) >= v_prev_start AND DATE(last_active_at) <= v_prev_end
    AND is_active = true;

  -- 复购用户：周期内已支付订单数 >= 2 的用户
  SELECT COUNT(*)::INTEGER INTO v_repurchase
  FROM (
    SELECT user_id
    FROM public.orders
    WHERE DATE(created_at) >= p_start_date AND DATE(created_at) <= p_end_date
      AND status = 2
    GROUP BY user_id
    HAVING COUNT(*) >= 2
  ) t;

  SELECT COUNT(*)::INTEGER INTO v_prev_repurchase
  FROM (
    SELECT user_id
    FROM public.orders
    WHERE DATE(created_at) >= v_prev_start AND DATE(created_at) <= v_prev_end
      AND status = 2
    GROUP BY user_id
    HAVING COUNT(*) >= 2
  ) t;

  RETURN QUERY
  SELECT
    v_total,
    CASE WHEN v_total > 0 AND v_prev_new > 0 THEN ((v_new - v_prev_new)::NUMERIC / v_prev_new * 100) ELSE 0 END,
    v_new,
    CASE WHEN v_prev_new > 0 THEN ((v_new - v_prev_new)::NUMERIC / v_prev_new * 100) ELSE (CASE WHEN v_new > 0 THEN 100 ELSE 0 END) END,
    CASE WHEN v_total > 0 THEN (v_active::NUMERIC / v_total * 100) ELSE 0 END,
    CASE WHEN v_prev_active > 0 THEN ((v_active - v_prev_active)::NUMERIC / v_prev_active * 100) ELSE (CASE WHEN v_active > 0 THEN 100 ELSE 0 END) END,
    CASE WHEN v_total > 0 THEN (v_repurchase::NUMERIC / v_total * 100) ELSE 0 END,
    CASE WHEN v_prev_repurchase > 0 THEN ((v_repurchase - v_prev_repurchase)::NUMERIC / v_prev_repurchase * 100) ELSE (CASE WHEN v_repurchase > 0 THEN 100 ELSE 0 END) END;
END;
$$;

-- 4.8 用户增长趋势（按天）
CREATE OR REPLACE FUNCTION rpc_analytics_user_growth_trend(
  p_start_date DATE,
  p_end_date DATE
)
RETURNS TABLE (
  date DATE,
  new_users INTEGER,
  total_users INTEGER
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
DECLARE
  v_total_before INTEGER := 0;
BEGIN
  IF auth.uid() IS NULL THEN
    RAISE EXCEPTION 'unauthorized';
  END IF;

  SELECT COUNT(*)::INTEGER INTO v_total_before
  FROM public.users
  WHERE DATE(created_at) < p_start_date;

  RETURN QUERY
  WITH days AS (
    SELECT generate_series(p_start_date, p_end_date, interval '1 day')::date AS d
  ),
  nu AS (
    SELECT DATE(created_at) AS d, COUNT(*)::INTEGER AS c
    FROM public.users
    WHERE DATE(created_at) >= p_start_date AND DATE(created_at) <= p_end_date
    GROUP BY DATE(created_at)
  ),
  joined AS (
    SELECT days.d, COALESCE(nu.c, 0) AS new_users
    FROM days
    LEFT JOIN nu ON nu.d = days.d
    ORDER BY days.d
  )
  SELECT
    joined.d AS date,
    joined.new_users,
    (v_total_before + SUM(joined.new_users) OVER (ORDER BY joined.d))::INTEGER AS total_users
  FROM joined;
END;
$$;

-- ============================================
-- 5. 触发器（自动更新 updated_at）
-- ============================================

-- 为需要的表添加触发器
DO $$
BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_analytics_user_preferences_updated_at') THEN
    EXECUTE 'CREATE TRIGGER update_analytics_user_preferences_updated_at BEFORE UPDATE ON public.analytics_user_preferences FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column()';
  END IF;
  IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_analytics_reports_updated_at') THEN
    EXECUTE 'CREATE TRIGGER update_analytics_reports_updated_at BEFORE UPDATE ON public.analytics_reports FOR EACH ROW EXECUTE FUNCTION public.update_updated_at_column()';
  END IF;
END $$;

-- ============================================
-- 完成
-- ============================================

-- ============================================
-- 6. RPC 授权收敛（只允许 authenticated 调用）
-- ============================================

REVOKE ALL ON FUNCTION rpc_analytics_realtime_kpis(TIMESTAMPTZ, TIMESTAMPTZ, TIMESTAMPTZ, TIMESTAMPTZ, UUID) FROM PUBLIC;
REVOKE ALL ON FUNCTION rpc_analytics_trend_data(DATE, DATE, UUID) FROM PUBLIC;
REVOKE ALL ON FUNCTION rpc_analytics_top_products(DATE, DATE, INTEGER, UUID) FROM PUBLIC;
REVOKE ALL ON FUNCTION rpc_analytics_top_merchants(DATE, DATE, INTEGER) FROM PUBLIC;
REVOKE ALL ON FUNCTION rpc_analytics_user_segments(DATE, DATE) FROM PUBLIC;
REVOKE ALL ON FUNCTION rpc_analytics_traffic_sources(DATE, DATE) FROM PUBLIC;
REVOKE ALL ON FUNCTION rpc_analytics_user_kpis(DATE, DATE) FROM PUBLIC;
REVOKE ALL ON FUNCTION rpc_analytics_user_growth_trend(DATE, DATE) FROM PUBLIC;

GRANT EXECUTE ON FUNCTION rpc_analytics_realtime_kpis(TIMESTAMPTZ, TIMESTAMPTZ, TIMESTAMPTZ, TIMESTAMPTZ, UUID) TO authenticated;
GRANT EXECUTE ON FUNCTION rpc_analytics_trend_data(DATE, DATE, UUID) TO authenticated;
GRANT EXECUTE ON FUNCTION rpc_analytics_top_products(DATE, DATE, INTEGER, UUID) TO authenticated;
GRANT EXECUTE ON FUNCTION rpc_analytics_top_merchants(DATE, DATE, INTEGER) TO authenticated;
GRANT EXECUTE ON FUNCTION rpc_analytics_user_segments(DATE, DATE) TO authenticated;
GRANT EXECUTE ON FUNCTION rpc_analytics_traffic_sources(DATE, DATE) TO authenticated;
GRANT EXECUTE ON FUNCTION rpc_analytics_user_kpis(DATE, DATE) TO authenticated;
GRANT EXECUTE ON FUNCTION rpc_analytics_user_growth_trend(DATE, DATE) TO authenticated;

-- ============================================
-- 完成
-- ============================================

SELECT 'Analytics database schema created successfully!' AS message;
