-- 训练偏好分析系统数据库扩展 (修正版)
-- 用于支持训练偏好分析功能的表和函数

-- 用户偏好历史记录表
CREATE TABLE IF NOT EXISTS public.ak_user_preference_history (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id uuid REFERENCES public.ak_users(id) ON DELETE CASCADE,
    sport_type_id uuid REFERENCES public.ak_sport_types(id),
    action_type VARCHAR(32) NOT NULL, -- 'created', 'updated', 'deleted', 'favorite_added', 'favorite_removed'
    old_values JSONB, -- 旧值
    new_values JSONB, -- 新值
    created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
);
COMMENT ON TABLE public.ak_user_preference_history IS '用户偏好历史记录表';
CREATE INDEX IF NOT EXISTS idx_preference_history_user_id ON public.ak_user_preference_history(user_id);
CREATE INDEX IF NOT EXISTS idx_preference_history_action ON public.ak_user_preference_history(action_type);
CREATE INDEX IF NOT EXISTS idx_preference_history_date ON public.ak_user_preference_history(created_at);

-- 目标历史记录表
CREATE TABLE IF NOT EXISTS public.ak_goal_progress_history (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    goal_id uuid REFERENCES public.ak_user_training_goals(id) ON DELETE CASCADE,
    user_id uuid REFERENCES public.ak_users(id) ON DELETE CASCADE,
    old_value FLOAT,
    new_value FLOAT,
    change_amount FLOAT,
    change_type VARCHAR(32), -- 'increase', 'decrease', 'target_adjusted'
    recorded_at TIMESTAMP WITH TIME ZONE DEFAULT now()
);
COMMENT ON TABLE public.ak_goal_progress_history IS '目标进度历史记录表';
CREATE INDEX IF NOT EXISTS idx_goal_progress_history_goal_id ON public.ak_goal_progress_history(goal_id);
CREATE INDEX IF NOT EXISTS idx_goal_progress_history_user_id ON public.ak_goal_progress_history(user_id);
CREATE INDEX IF NOT EXISTS idx_goal_progress_history_date ON public.ak_goal_progress_history(recorded_at);

-- 训练模式分析表
CREATE TABLE IF NOT EXISTS public.ak_training_patterns (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id uuid REFERENCES public.ak_users(id) ON DELETE CASCADE,
    pattern_type VARCHAR(32) NOT NULL, -- 'weekly_schedule', 'intensity_preference', 'duration_preference'
    pattern_data JSONB NOT NULL,
    confidence_score FLOAT DEFAULT 0.5, -- 置信度分数 0-1
    detected_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT now()
);
COMMENT ON TABLE public.ak_training_patterns IS '训练模式分析表';
CREATE INDEX IF NOT EXISTS idx_training_patterns_user_id ON public.ak_training_patterns(user_id);
CREATE INDEX IF NOT EXISTS idx_training_patterns_type ON public.ak_training_patterns(pattern_type);
CREATE UNIQUE INDEX IF NOT EXISTS idx_training_patterns_unique ON public.ak_training_patterns(user_id, pattern_type);

-- 个性化推荐记录表
CREATE TABLE IF NOT EXISTS public.ak_personalized_recommendations (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id uuid REFERENCES public.ak_users(id) ON DELETE CASCADE,
    recommendation_type VARCHAR(32) NOT NULL, -- 'sport', 'schedule', 'intensity', 'goal'
    title VARCHAR(128) NOT NULL,
    description TEXT,
    recommendation_data JSONB,
    reason TEXT, -- 推荐理由
    priority INT DEFAULT 1, -- 优先级 1-5
    status VARCHAR(16) DEFAULT 'pending', -- 'pending', 'viewed', 'applied', 'dismissed'
    created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
    viewed_at TIMESTAMP WITH TIME ZONE,
    applied_at TIMESTAMP WITH TIME ZONE
);
COMMENT ON TABLE public.ak_personalized_recommendations IS '个性化推荐记录表';
CREATE INDEX IF NOT EXISTS idx_recommendations_user_id ON public.ak_personalized_recommendations(user_id);
CREATE INDEX IF NOT EXISTS idx_recommendations_status ON public.ak_personalized_recommendations(status);
CREATE INDEX IF NOT EXISTS idx_recommendations_type ON public.ak_personalized_recommendations(recommendation_type);

-- 用户行为分析表
CREATE TABLE IF NOT EXISTS public.ak_user_behavior_analytics (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id uuid REFERENCES public.ak_users(id) ON DELETE CASCADE,
    behavior_type VARCHAR(32) NOT NULL, -- 'preference_change', 'goal_setting', 'reminder_usage', 'device_sync'
    behavior_data JSONB,
    session_id uuid, -- 用于关联同一会话的行为
    created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
);
COMMENT ON TABLE public.ak_user_behavior_analytics IS '用户行为分析表';
CREATE INDEX IF NOT EXISTS idx_behavior_analytics_user_id ON public.ak_user_behavior_analytics(user_id);
CREATE INDEX IF NOT EXISTS idx_behavior_analytics_type ON public.ak_user_behavior_analytics(behavior_type);
CREATE INDEX IF NOT EXISTS idx_behavior_analytics_date ON public.ak_user_behavior_analytics(created_at);

-- 创建获取用户偏好分析数据的函数
CREATE OR REPLACE FUNCTION get_user_preferences_analytics(p_user_id uuid)
RETURNS JSONB AS $$
DECLARE
    result JSONB := '{}'::JSONB;
    favorite_count INT;
    weekly_hours FLOAT;
    category_stats JSONB;
    intensity_stats JSONB;
    trend_data JSONB;
BEGIN
    -- 获取喜爱运动数量
    SELECT COUNT(*) INTO favorite_count
    FROM public.ak_user_sport_preferences
    WHERE user_id = p_user_id AND is_favorite = true;
    
    -- 计算每周训练时长
    SELECT COALESCE(SUM(frequency_per_week * duration_minutes), 0) / 60.0 INTO weekly_hours
    FROM public.ak_user_sport_preferences
    WHERE user_id = p_user_id;
    
    -- 获取运动类型分布
    SELECT jsonb_agg(
        jsonb_build_object(
            'category', st.category,
            'count', category_count,
            'percentage', ROUND((category_count::FLOAT / total_count::FLOAT) * 100, 1)
        )
    ) INTO category_stats
    FROM (
        SELECT 
            st.category,
            COUNT(*) as category_count,
            (SELECT COUNT(*) FROM public.ak_user_sport_preferences WHERE user_id = p_user_id) as total_count
        FROM public.ak_user_sport_preferences usp
        JOIN public.ak_sport_types st ON usp.sport_type_id = st.id
        WHERE usp.user_id = p_user_id
        GROUP BY st.category
    ) category_data;
    
    -- 获取强度分析
    SELECT jsonb_agg(
        jsonb_build_object(
            'intensity_level', intensity_level,
            'count', level_count,
            'percentage', ROUND((level_count::FLOAT / total_count::FLOAT) * 100, 1)
        )
    ) INTO intensity_stats
    FROM (
        SELECT 
            intensity_level,
            COUNT(*) as level_count,
            (SELECT COUNT(*) FROM public.ak_user_sport_preferences WHERE user_id = p_user_id) as total_count
        FROM public.ak_user_sport_preferences
        WHERE user_id = p_user_id
        GROUP BY intensity_level
    ) intensity_data;
    
    -- 获取趋势数据（最近30天的偏好变化）
    SELECT jsonb_agg(
        jsonb_build_object(
            'date', date_trunc('day', created_at),
            'action_type', action_type,
            'count', action_count
        )
    ) INTO trend_data
    FROM (
        SELECT 
            created_at,
            action_type,
            COUNT(*) as action_count
        FROM public.ak_user_preference_history
        WHERE user_id = p_user_id 
        AND created_at >= NOW() - INTERVAL '30 days'
        GROUP BY date_trunc('day', created_at), action_type
        ORDER BY created_at DESC
    ) trend_history;
    
    -- 构建结果
    result = jsonb_build_object(
        'favorite_count', favorite_count,
        'weekly_hours', weekly_hours,
        'category_distribution', COALESCE(category_stats, '[]'::JSONB),
        'intensity_analysis', COALESCE(intensity_stats, '[]'::JSONB),
        'trend_data', COALESCE(trend_data, '[]'::JSONB)
    );
    
    RETURN result;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- 创建生成个性化推荐的函数
CREATE OR REPLACE FUNCTION generate_personalized_recommendations(p_user_id uuid)
RETURNS VOID AS $$
DECLARE
    user_preferences RECORD;
    recommendation_count INT;
BEGIN
    -- 清理旧的待处理推荐
    DELETE FROM public.ak_personalized_recommendations 
    WHERE user_id = p_user_id 
    AND status = 'pending' 
    AND created_at < NOW() - INTERVAL '7 days';
    
    -- 获取用户偏好信息
    SELECT 
        COUNT(*) as total_preferences,
        COUNT(*) FILTER (WHERE is_favorite = true) as favorite_count,
        AVG(intensity_level) as avg_intensity,
        SUM(frequency_per_week * duration_minutes) as weekly_minutes
    INTO user_preferences
    FROM public.ak_user_sport_preferences
    WHERE user_id = p_user_id;
    
    -- 检查是否需要扩展运动偏好
    IF user_preferences.favorite_count < 3 THEN
        INSERT INTO public.ak_personalized_recommendations (
            user_id, recommendation_type, title, description, reason, priority
        ) VALUES (
            p_user_id, 'sport', '扩展运动偏好', 
            '尝试添加更多喜爱的运动类型，让训练更有趣',
            '当前喜爱运动少于3种', 3
        );
    END IF;
    
    -- 检查是否需要增加训练时间
    IF user_preferences.weekly_minutes < 180 THEN -- 少于3小时
        INSERT INTO public.ak_personalized_recommendations (
            user_id, recommendation_type, title, description, reason, priority
        ) VALUES (
            p_user_id, 'schedule', '增加训练时间', 
            '建议每周至少进行3小时的体育锻炼',
            '当前每周训练时间不足', 4
        );
    END IF;
    
    -- 检查是否需要调整训练强度
    IF user_preferences.avg_intensity < 2.5 THEN
        INSERT INTO public.ak_personalized_recommendations (
            user_id, recommendation_type, title, description, reason, priority
        ) VALUES (
            p_user_id, 'intensity', '增加训练强度', 
            '适当增加高强度训练可以提高运动效果',
            '当前训练强度偏低', 2
        );
    END IF;
    
    -- 检查是否需要设定目标
    SELECT COUNT(*) INTO recommendation_count
    FROM public.ak_user_training_goals
    WHERE user_id = p_user_id AND status = 'active';
    
    IF recommendation_count = 0 THEN
        INSERT INTO public.ak_personalized_recommendations (
            user_id, recommendation_type, title, description, reason, priority
        ) VALUES (
            p_user_id, 'goal', '设定训练目标', 
            '设定明确的训练目标有助于保持动力',
            '当前没有活跃的训练目标', 5
        );
    END IF;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- 创建记录用户行为的函数
CREATE OR REPLACE FUNCTION log_user_behavior(
    p_user_id uuid,
    p_behavior_type VARCHAR(32),
    p_behavior_data JSONB DEFAULT NULL,
    p_session_id uuid DEFAULT NULL
)
RETURNS VOID AS $$
BEGIN
    INSERT INTO public.ak_user_behavior_analytics (
        user_id, behavior_type, behavior_data, session_id
    ) VALUES (
        p_user_id, p_behavior_type, p_behavior_data, p_session_id
    );
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- 创建更新训练模式的函数
CREATE OR REPLACE FUNCTION update_training_pattern(
    p_user_id uuid,
    p_pattern_type VARCHAR(32),
    p_pattern_data JSONB,
    p_confidence_score FLOAT DEFAULT 0.5
)
RETURNS VOID AS $$
BEGIN
    INSERT INTO public.ak_training_patterns (
        user_id, pattern_type, pattern_data, confidence_score
    ) VALUES (
        p_user_id, p_pattern_type, p_pattern_data, p_confidence_score
    )
    ON CONFLICT (user_id, pattern_type) 
    DO UPDATE SET 
        pattern_data = EXCLUDED.pattern_data,
        confidence_score = EXCLUDED.confidence_score,
        updated_at = NOW();
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- 创建获取用户训练趋势的函数 (修正版)
CREATE OR REPLACE FUNCTION get_user_training_trends(
    p_user_id uuid,
    p_days INT DEFAULT 30
)
RETURNS JSONB AS $$
DECLARE
    result JSONB := '[]'::JSONB;
    trend_item JSONB;
    interval_text TEXT;
BEGIN
    -- 构建间隔文本
    interval_text := p_days || ' days';
    
    -- 获取目标完成趋势
    WITH goal_trends AS (
        SELECT 
            date_trunc('day', recorded_at) as trend_date,
            COUNT(*) as changes_count,
            AVG(change_amount) as avg_change
        FROM public.ak_goal_progress_history
        WHERE user_id = p_user_id
        AND recorded_at >= NOW() - interval_text::INTERVAL
        GROUP BY date_trunc('day', recorded_at)
        ORDER BY trend_date
    )
    SELECT jsonb_agg(
        jsonb_build_object(
            'date', trend_date,
            'type', 'goal_progress',
            'value', avg_change,
            'count', changes_count
        )
    ) INTO trend_item
    FROM goal_trends;
    
    result = result || COALESCE(trend_item, '[]'::JSONB);
    
    -- 获取偏好变化趋势
    WITH preference_trends AS (
        SELECT 
            date_trunc('day', created_at) as trend_date,
            action_type,
            COUNT(*) as action_count
        FROM public.ak_user_preference_history
        WHERE user_id = p_user_id
        AND created_at >= NOW() - interval_text::INTERVAL
        GROUP BY date_trunc('day', created_at), action_type
        ORDER BY trend_date
    )
    SELECT jsonb_agg(
        jsonb_build_object(
            'date', trend_date,
            'type', 'preference_change',
            'action_type', action_type,
            'count', action_count
        )
    ) INTO trend_item
    FROM preference_trends;
    
    result = result || COALESCE(trend_item, '[]'::JSONB);
    
    RETURN result;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- 创建触发器函数来自动记录偏好变化
CREATE OR REPLACE FUNCTION track_preference_changes()
RETURNS TRIGGER AS $$
BEGIN
    IF TG_OP = 'INSERT' THEN
        INSERT INTO public.ak_user_preference_history (
            user_id, sport_type_id, action_type, new_values
        ) VALUES (
            NEW.user_id, NEW.sport_type_id, 'created', to_jsonb(NEW)
        );
        RETURN NEW;
    ELSIF TG_OP = 'UPDATE' THEN
        INSERT INTO public.ak_user_preference_history (
            user_id, sport_type_id, action_type, old_values, new_values
        ) VALUES (
            NEW.user_id, NEW.sport_type_id, 'updated', to_jsonb(OLD), to_jsonb(NEW)
        );
        RETURN NEW;
    ELSIF TG_OP = 'DELETE' THEN
        INSERT INTO public.ak_user_preference_history (
            user_id, sport_type_id, action_type, old_values
        ) VALUES (
            OLD.user_id, OLD.sport_type_id, 'deleted', to_jsonb(OLD)
        );
        RETURN OLD;
    END IF;
    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

-- 创建触发器函数来自动记录目标进度变化
CREATE OR REPLACE FUNCTION track_goal_progress_changes()
RETURNS TRIGGER AS $$
BEGIN
    IF TG_OP = 'UPDATE' AND OLD.current_value IS DISTINCT FROM NEW.current_value THEN
        INSERT INTO public.ak_goal_progress_history (
            goal_id, user_id, old_value, new_value, change_amount, change_type
        ) VALUES (
            NEW.id, NEW.user_id, OLD.current_value, NEW.current_value,
            NEW.current_value - OLD.current_value,
            CASE 
                WHEN NEW.current_value > OLD.current_value THEN 'increase'
                ELSE 'decrease'
            END
        );
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 删除可能存在的旧触发器
DROP TRIGGER IF EXISTS preference_changes_trigger ON public.ak_user_sport_preferences;
DROP TRIGGER IF EXISTS goal_progress_changes_trigger ON public.ak_user_training_goals;

-- 创建新触发器
CREATE TRIGGER preference_changes_trigger
    AFTER INSERT OR UPDATE OR DELETE ON public.ak_user_sport_preferences
    FOR EACH ROW EXECUTE FUNCTION track_preference_changes();

CREATE TRIGGER goal_progress_changes_trigger
    AFTER UPDATE ON public.ak_user_training_goals
    FOR EACH ROW EXECUTE FUNCTION track_goal_progress_changes();

-- 清理任何可能存在的示例数据
DELETE FROM public.ak_personalized_recommendations WHERE recommendation_type = 'sport' AND title = '尝试新的运动类型';

-- 插入一些示例推荐数据（如果用户表存在）
DO $$
BEGIN
    IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'ak_users' AND table_schema = 'public') THEN
        INSERT INTO public.ak_personalized_recommendations (
            user_id, recommendation_type, title, description, reason, priority
        ) 
        SELECT 
            id as user_id,
            'sport' as recommendation_type,
            '尝试新的运动类型' as title,
            '根据您的偏好，我们推荐您尝试瑜伽或游泳' as description,
            '扩展运动种类有助于全面发展' as reason,
            3 as priority
        FROM public.ak_users 
        WHERE role = 'student'
        LIMIT 5;
    END IF;
END $$;
