-- =====================================================================================
-- 商城分析模块 RPC 函数增量脚本
-- 依赖: ml_* 系列表, ak_users 表
-- 目标: 为数据分析模块提供核心数据接口，优先使用现有表，不新建表。
-- =====================================================================================

-- =====================================================================================
-- 1. 函数: rpc_analytics_user_kpis
-- 描述: 获取用户分析核心KPI指标，并与上一周期对比。
-- =====================================================================================
CREATE OR REPLACE FUNCTION public.rpc_analytics_user_kpis(
    p_start_date DATE,
    p_end_date DATE
)
RETURNS TABLE (
    total_users BIGINT,
    user_growth FLOAT,
    new_users BIGINT,
    new_user_growth FLOAT,
    active_users BIGINT,
    active_growth FLOAT,
    ordering_users BIGINT,
    ordering_growth FLOAT,
    paid_users BIGINT,
    paid_growth FLOAT,
    new_user_conversion_rate FLOAT,
    repurchase_rate FLOAT,
    repurchase_growth FLOAT
)
LANGUAGE plpgsql
AS $$
DECLARE
    prev_start_date DATE;
    prev_end_date DATE;
    period_days INT;
BEGIN
    -- 计算上一周期日期范围
    period_days := p_end_date - p_start_date + 1;
    prev_start_date := p_start_date - period_days;
    prev_end_date := p_start_date - 1;

    RETURN QUERY
    WITH
    -- 当前周期数据
    current_period AS (
        SELECT
            (SELECT COUNT(*) FROM public.ak_users WHERE created_at <= p_end_date::timestamp) AS total_users,
            COUNT(DISTINCT CASE WHEN u.created_at::DATE BETWEEN p_start_date AND p_end_date THEN u.id END)::BIGINT AS new_users,
            (SELECT COUNT(DISTINCT bh.user_id) FROM public.ml_browse_history bh WHERE bh.created_at::DATE BETWEEN p_start_date AND p_end_date) AS active_users,
            (SELECT COUNT(DISTINCT o.user_id) FROM public.ml_orders o WHERE o.created_at::DATE BETWEEN p_start_date AND p_end_date) AS ordering_users,
            (SELECT COUNT(DISTINCT o.user_id) FROM public.ml_orders o WHERE o.created_at::DATE BETWEEN p_start_date AND p_end_date AND o.payment_status = 2) AS paid_users,
            (
                SELECT COUNT(DISTINCT o.user_id) * 100.0 / NULLIF(COUNT(DISTINCT u_new.id), 0)
                FROM public.ak_users u_new
                LEFT JOIN public.ml_orders o ON u_new.id = o.user_id AND o.payment_status = 2 AND o.created_at::DATE BETWEEN p_start_date AND p_end_date
                WHERE u_new.created_at::DATE BETWEEN p_start_date AND p_end_date
            ) AS new_user_conversion_rate,
            (
                SELECT COUNT(DISTINCT CASE WHEN user_orders.order_count > 1 THEN user_orders.user_id END) * 100.0 / NULLIF(COUNT(DISTINCT user_orders.user_id), 0)
                FROM (
                    SELECT user_id, COUNT(id) as order_count
                    FROM public.ml_orders
                    WHERE created_at::DATE <= p_end_date AND payment_status = 2
                    GROUP BY user_id
                ) user_orders
                WHERE user_orders.user_id IN (SELECT user_id FROM public.ml_orders WHERE created_at::DATE BETWEEN p_start_date AND p_end_date AND payment_status = 2)
            ) AS repurchase_rate
        FROM public.ak_users u
    ),
    -- 上一周期数据
    previous_period AS (
        SELECT
            (SELECT COUNT(*) FROM public.ak_users WHERE created_at <= prev_end_date::timestamp) AS total_users,
            COUNT(DISTINCT CASE WHEN u.created_at::DATE BETWEEN prev_start_date AND prev_end_date THEN u.id END)::BIGINT AS new_users,
            (SELECT COUNT(DISTINCT bh.user_id) FROM public.ml_browse_history bh WHERE bh.created_at::DATE BETWEEN prev_start_date AND prev_end_date) AS active_users,
            (SELECT COUNT(DISTINCT o.user_id) FROM public.ml_orders o WHERE o.created_at::DATE BETWEEN prev_start_date AND prev_end_date) AS ordering_users,
            (SELECT COUNT(DISTINCT o.user_id) FROM public.ml_orders o WHERE o.created_at::DATE BETWEEN prev_start_date AND prev_end_date AND o.payment_status = 2) AS paid_users,
            (
                SELECT COUNT(DISTINCT CASE WHEN user_orders.order_count > 1 THEN user_orders.user_id END) * 100.0 / NULLIF(COUNT(DISTINCT user_orders.user_id), 0)
                FROM (
                    SELECT user_id, COUNT(id) as order_count
                    FROM public.ml_orders
                    WHERE created_at::DATE <= prev_end_date AND payment_status = 2
                    GROUP BY user_id
                ) user_orders
                WHERE user_orders.user_id IN (SELECT user_id FROM public.ml_orders WHERE created_at::DATE BETWEEN prev_start_date AND prev_end_date AND payment_status = 2)
            ) AS repurchase_rate
        FROM public.ak_users u
    )
    SELECT
        cp.total_users,
        ROUND(((cp.total_users - pp.total_users) * 100.0 / NULLIF(pp.total_users, 0))::numeric, 2)::FLOAT AS user_growth,
        cp.new_users,
        ROUND(((cp.new_users - pp.new_users) * 100.0 / NULLIF(pp.new_users, 0))::numeric, 2)::FLOAT AS new_user_growth,
        cp.active_users,
        ROUND(((cp.active_users - pp.active_users) * 100.0 / NULLIF(pp.active_users, 0))::numeric, 2)::FLOAT AS active_growth,
        cp.ordering_users,
        ROUND(((cp.ordering_users - pp.ordering_users) * 100.0 / NULLIF(pp.ordering_users, 0))::numeric, 2)::FLOAT AS ordering_growth,
        cp.paid_users,
        ROUND(((cp.paid_users - pp.paid_users) * 100.0 / NULLIF(pp.paid_users, 0))::numeric, 2)::FLOAT AS paid_growth,
        ROUND(cp.new_user_conversion_rate::numeric, 2)::FLOAT,
        ROUND(cp.repurchase_rate::numeric, 2)::FLOAT AS repurchase_rate,
        ROUND((COALESCE(cp.repurchase_rate, 0) - COALESCE(pp.repurchase_rate, 0))::numeric, 2)::FLOAT AS repurchase_growth
    FROM current_period cp, previous_period pp;
END;
$$;

-- -------------------------------------------------------------------------------------
-- 2. 函数: rpc_analytics_user_growth_trend
-- 描述: 获取用户增长与活跃趋势（日维度）
-- -------------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION public.rpc_analytics_user_growth_trend(
    p_start_date DATE,
    p_end_date DATE
)
RETURNS TABLE (
    date DATE,
    new_users BIGINT,
    active_users BIGINT
)
LANGUAGE sql
AS $$
    WITH date_series AS (
        SELECT generate_series(p_start_date, p_end_date, '1 day'::interval)::DATE AS date
    )
    SELECT
        ds.date,
        (SELECT COUNT(u.id) FROM public.ak_users u WHERE u.created_at::DATE = ds.date)::BIGINT AS new_users,
        (SELECT COUNT(DISTINCT bh.user_id) FROM public.ml_browse_history bh WHERE bh.created_at::DATE = ds.date)::BIGINT AS active_users
    FROM date_series ds
    ORDER BY ds.date;
$$;

-- -------------------------------------------------------------------------------------
-- 3. 函数: rpc_analytics_user_segments
-- 描述: 获取用户分群（基于新老客、复购的简单模型）
-- -------------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION public.rpc_analytics_user_segments(
    p_start_date DATE,
    p_end_date DATE
)
RETURNS TABLE (
    name TEXT,
    value BIGINT
)
LANGUAGE sql
AS $$
    WITH user_orders_stats AS (
        SELECT
            user_id,
            MIN(created_at) as first_order_time,
            COUNT(id) as total_orders
        FROM public.ml_orders
        WHERE payment_status = 2
        GROUP BY user_id
    ),
    active_users_in_period AS (
        SELECT DISTINCT user_id FROM public.ml_orders WHERE created_at::DATE BETWEEN p_start_date AND p_end_date
    )
    SELECT
        segment as name,
        COUNT(user_id) as value
    FROM (
        SELECT
            auip.user_id,
            CASE
                WHEN uos.first_order_time::DATE BETWEEN p_start_date AND p_end_date THEN '新客'
                WHEN uos.total_orders > 1 THEN '复购客户'
                ELSE '老客'
            END as segment
        FROM active_users_in_period auip
        JOIN user_orders_stats uos ON auip.user_id = uos.user_id
    ) segments
    GROUP BY segment;
$$;

-- -------------------------------------------------------------------------------------
-- 4. 函数: rpc_analytics_traffic_sources
-- 描述: 获取流量来源分布 (基于注册来源)
-- 兼容性说明：部分环境的 ak_users 可能不存在 registration_source 字段。
-- 为避免 RPC 报错导致页面加载失败，这里做“字段存在则分组统计，不存在则全部归为未知”的兼容。
-- -------------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION public.rpc_analytics_traffic_sources(
    p_start_date DATE,
    p_end_date DATE
)
RETURNS TABLE (
    name TEXT,
    value BIGINT
)
LANGUAGE plpgsql
AS $
DECLARE
    has_registration_source BOOLEAN := FALSE;
BEGIN
    SELECT EXISTS (
        SELECT 1
        FROM information_schema.columns
        WHERE table_schema = 'public'
          AND table_name = 'ak_users'
          AND column_name = 'registration_source'
    ) INTO has_registration_source;

    IF has_registration_source THEN
        RETURN QUERY
        EXECUTE '
            SELECT
                COALESCE(registration_source, ''未知'') AS name,
                COUNT(id)::BIGINT AS value
            FROM public.ak_users
            WHERE created_at::DATE BETWEEN $1 AND $2
            GROUP BY name
            ORDER BY value DESC
        '
        USING p_start_date, p_end_date;
    ELSE
        RETURN QUERY
        SELECT '未知'::TEXT AS name,
               COUNT(id)::BIGINT AS value
        FROM public.ak_users
        WHERE created_at::DATE BETWEEN p_start_date AND p_end_date;
    END IF;
END;
$;

-- =====================================================================================
-- 5. 完成提示
-- =====================================================================================

DO $$
BEGIN
    RAISE NOTICE '=======================================================';
    RAISE NOTICE '商城分析模块 RPC 函数创建/更新完成！';
    RAISE NOTICE '=======================================================';
    RAISE NOTICE '✓ RPC 函数创建/更新完成:';
    RAISE NOTICE '  - rpc_analytics_user_kpis';
    RAISE NOTICE '  - rpc_analytics_user_growth_trend';
    RAISE NOTICE '  - rpc_analytics_user_segments';
    RAISE NOTICE '  - rpc_analytics_traffic_sources';
    RAISE NOTICE '=======================================================';
    RAISE NOTICE '下一步:';
    RAISE NOTICE '1. 在数据库中执行此脚本。';
    RAISE NOTICE '2. 确认前端 user-analysis.uvue 页面已调用这些 RPC。';
    RAISE NOTICE '3. 如果缺少活跃数据，请确保 ml_browse_history 表有数据写入。';
    RAISE NOTICE '=======================================================';
END $$;
