-- 学生成就系统表结构
-- 用于记录学生获得的各种成就和徽章

-- 成就定义表
CREATE TABLE IF NOT EXISTS public.ak_achievements (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(128) NOT NULL UNIQUE, -- 成就名称 (添加唯一约束)
    description TEXT, -- 成就描述
    category VARCHAR(32) DEFAULT 'general', -- 成就分类 (training, skill, progress, persistence, special)
    difficulty VARCHAR(16) DEFAULT 'easy', -- 难度等级 (easy, medium, hard, expert)
    points INT DEFAULT 10, -- 奖励积分
    icon VARCHAR(16) DEFAULT '🏆', -- 成就图标
    requirements TEXT, -- 获得条件说明
    is_active BOOLEAN DEFAULT true, -- 是否启用
    sort_order INT DEFAULT 0, -- 排序顺序
    created_at TIMESTAMP WITH TIME ZONE DEFAULT now(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT now()
);
COMMENT ON TABLE public.ak_achievements IS '成就定义表';

-- 学生成就记录表
CREATE TABLE IF NOT EXISTS public.ak_student_achievements (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    student_id uuid REFERENCES public.ak_users(id) ON DELETE CASCADE, -- 学生ID
    achievement_id uuid REFERENCES public.ak_achievements(id) ON DELETE CASCADE, -- 成就ID
    unlocked_at TIMESTAMP WITH TIME ZONE DEFAULT now(), -- 获得时间
    progress_current INT DEFAULT 0, -- 当前进度
    progress_target INT DEFAULT 1, -- 目标进度
    is_featured BOOLEAN DEFAULT false, -- 是否为精选成就
    created_at TIMESTAMP WITH TIME ZONE DEFAULT now()
);
COMMENT ON TABLE public.ak_student_achievements IS '学生成就记录表';

-- 创建索引
CREATE INDEX IF NOT EXISTS idx_achievements_category ON public.ak_achievements(category);
CREATE INDEX IF NOT EXISTS idx_achievements_difficulty ON public.ak_achievements(difficulty);
CREATE INDEX IF NOT EXISTS idx_student_achievements_student_id ON public.ak_student_achievements(student_id);
CREATE INDEX IF NOT EXISTS idx_student_achievements_achievement_id ON public.ak_student_achievements(achievement_id);
CREATE INDEX IF NOT EXISTS idx_student_achievements_unlocked_at ON public.ak_student_achievements(unlocked_at);

-- 防止重复获得同一成就
ALTER TABLE public.ak_student_achievements 
ADD CONSTRAINT uk_student_achievement_unique UNIQUE (student_id, achievement_id);

-- 插入一些基础成就
INSERT INTO public.ak_achievements (name, description, category, difficulty, points, icon, requirements) VALUES
('初出茅庐', '完成第一次训练记录', 'training', 'easy', 10, '🎯', '完成任意一次训练记录'),
('坚持不懈', '连续训练7天', 'persistence', 'medium', 50, '🔥', '连续7天都有训练记录'),
('技术精进', '单项技能评分达到90分以上', 'skill', 'hard', 100, '⚡', '在任意技能项目中获得90分以上评分'),
('全能选手', '完成所有训练项目', 'training', 'expert', 200, '🏆', '完成系统中所有的训练项目'),
('进步之星', '单月内平均分提升10分以上', 'progress', 'medium', 75, '📈', '在一个月内平均成绩提升10分或以上'),
('月度之王', '成为月度训练积分第一名', 'special', 'expert', 300, '👑', '在月度排行榜中获得第一名')
ON CONFLICT (name) DO NOTHING;

-- 创建触发器函数，自动检查成就获得条件
CREATE OR REPLACE FUNCTION check_student_achievements()
RETURNS TRIGGER AS $$
DECLARE
    student_uuid uuid;
    achievement_uuid uuid;
    assignment_count INT;
    avg_score FLOAT;
    consecutive_days INT;
BEGIN
    -- 获取学生ID
    student_uuid := NEW.student_id;
    
    -- 检查"初出茅庐"成就 - 完成第一次训练记录
    SELECT id INTO achievement_uuid FROM public.ak_achievements WHERE name = '初出茅庐';
    IF achievement_uuid IS NOT NULL THEN
        SELECT COUNT(*) INTO assignment_count 
        FROM public.ak_assignment_submissions 
        WHERE student_id = student_uuid AND status = 'submitted';
        
        IF assignment_count = 1 THEN
            INSERT INTO public.ak_student_achievements (student_id, achievement_id)
            VALUES (student_uuid, achievement_uuid)
            ON CONFLICT (student_id, achievement_id) DO NOTHING;
        END IF;
    END IF;
    
    -- 检查"技术精进"成就 - 90分以上评分
    SELECT id INTO achievement_uuid FROM public.ak_achievements WHERE name = '技术精进';
    IF achievement_uuid IS NOT NULL AND NEW.final_score >= 90 THEN
        INSERT INTO public.ak_student_achievements (student_id, achievement_id)
        VALUES (student_uuid, achievement_uuid)
        ON CONFLICT (student_id, achievement_id) DO NOTHING;
    END IF;
    
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 创建触发器
DROP TRIGGER IF EXISTS trigger_check_achievements ON public.ak_assignment_submissions;
CREATE TRIGGER trigger_check_achievements
    AFTER INSERT OR UPDATE ON public.ak_assignment_submissions
    FOR EACH ROW
    EXECUTE FUNCTION check_student_achievements();

-- 创建获取用户成就统计的函数
CREATE OR REPLACE FUNCTION get_student_achievement_stats(p_student_id uuid)
RETURNS TABLE(
    total_achievements INT,
    total_points INT,
    completion_rate FLOAT,
    recent_achievements_count INT
) AS $$
BEGIN
    RETURN QUERY
    SELECT 
        COUNT(sa.id)::INT as total_achievements,
        COALESCE(SUM(a.points), 0)::INT as total_points,
        CASE 
            WHEN COUNT(DISTINCT a_all.id) > 0 
            THEN (COUNT(sa.id)::FLOAT / COUNT(DISTINCT a_all.id) * 100)
            ELSE 0.0
        END as completion_rate,
        COUNT(CASE WHEN sa.unlocked_at >= NOW() - INTERVAL '7 days' THEN 1 END)::INT as recent_achievements_count
    FROM public.ak_achievements a_all
    LEFT JOIN public.ak_student_achievements sa ON a_all.id = sa.achievement_id AND sa.student_id = p_student_id
    LEFT JOIN public.ak_achievements a ON sa.achievement_id = a.id
    WHERE a_all.is_active = true;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
