-- =====================================================
-- 修复RLS策略无限递归错误
-- 解决 "infinite recursion detected in policy" 错误
-- =====================================================

-- 第一步：删除所有可能导致递归的策略
DO $$
DECLARE
    r RECORD;
BEGIN
    RAISE NOTICE '🧹 删除可能导致递归的策略';
    
    -- 删除所有消息相关表的策略
    FOR r IN 
        SELECT schemaname, tablename, policyname 
        FROM pg_policies 
        WHERE schemaname = 'public' 
        AND tablename IN ('ak_messages', 'ak_message_recipients', 'ak_message_groups', 
                         'ak_message_group_members', 'ak_message_templates', 
                         'ak_user_message_preferences', 'ak_message_stats', 'ak_message_types')
    LOOP
        EXECUTE format('DROP POLICY IF EXISTS %I ON %I.%I', 
                      r.policyname, r.schemaname, r.tablename);
        RAISE NOTICE '  删除策略: %.%', r.tablename, r.policyname;
    END LOOP;
    
    RAISE NOTICE '✅ 策略清理完成';
END $$;

-- 第二步：重新创建安全的策略（避免递归）

-- 启用RLS
ALTER TABLE public.ak_message_types ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ak_messages ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ak_message_recipients ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ak_message_groups ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ak_message_group_members ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ak_message_templates ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ak_user_message_preferences ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.ak_message_stats ENABLE ROW LEVEL SECURITY;

-- 1. 消息类型策略（简单，无递归）
CREATE POLICY "authenticated_can_view_message_types" ON public.ak_message_types
    FOR SELECT USING (auth.role() = 'authenticated');

CREATE POLICY "admins_can_manage_message_types" ON public.ak_message_types
    FOR ALL USING (
        auth.jwt() ->> 'user_role' = 'admin'
    );

-- 2. 群组成员策略（修复递归问题）
CREATE POLICY "users_can_view_own_membership" ON public.ak_message_group_members
    FOR SELECT USING (
        -- 用户可以查看自己的成员记录
        user_id = auth.uid()
        OR
        -- 管理员可以查看所有成员
        auth.jwt() ->> 'user_role' = 'admin'
    );

CREATE POLICY "users_can_join_groups" ON public.ak_message_group_members
    FOR INSERT WITH CHECK (
        -- 用户可以加入群组（以自己的身份）
        user_id = auth.uid()
        OR
        -- 管理员可以添加任何成员
        auth.jwt() ->> 'user_role' = 'admin'
    );

CREATE POLICY "users_can_update_own_membership" ON public.ak_message_group_members
    FOR UPDATE USING (
        user_id = auth.uid()
        OR
        auth.jwt() ->> 'user_role' = 'admin'
    );

CREATE POLICY "users_can_leave_groups" ON public.ak_message_group_members
    FOR DELETE USING (
        user_id = auth.uid()
        OR
        auth.jwt() ->> 'user_role' = 'admin'
    );

-- 3. 群组策略（简化，避免复杂查询）
CREATE POLICY "users_can_view_public_groups" ON public.ak_message_groups
    FOR SELECT USING (
        -- 公开群组所有人可见
        is_public = true
        OR
        -- 群组创建者可见
        created_by = auth.uid()
        OR
        -- 管理员可见
        auth.jwt() ->> 'user_role' = 'admin'
    );

CREATE POLICY "authenticated_users_can_create_groups" ON public.ak_message_groups
    FOR INSERT WITH CHECK (
        auth.role() = 'authenticated' AND created_by = auth.uid()
    );

CREATE POLICY "creators_can_update_groups" ON public.ak_message_groups
    FOR UPDATE USING (
        created_by = auth.uid()
        OR
        auth.jwt() ->> 'user_role' = 'admin'
    );

CREATE POLICY "creators_can_delete_groups" ON public.ak_message_groups
    FOR DELETE USING (
        created_by = auth.uid()
        OR
        auth.jwt() ->> 'user_role' = 'admin'
    );

-- 4. 消息策略（简化，使用函数避免递归）
-- 创建辅助函数检查群组成员身份
CREATE OR REPLACE FUNCTION public.is_group_member(group_id UUID, user_id UUID)
RETURNS BOOLEAN AS $$
BEGIN
    RETURN EXISTS (
        SELECT 1 FROM public.ak_message_group_members
        WHERE ak_message_group_members.group_id = is_group_member.group_id
        AND ak_message_group_members.user_id = is_group_member.user_id
        AND status = 'active'
    );
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

CREATE POLICY "users_can_view_relevant_messages" ON public.ak_messages
    FOR SELECT USING (
        -- 用户是发送者
        (sender_type = 'user' AND sender_id = auth.uid()) 
        OR
        -- 用户是接收者（单用户消息）
        (receiver_type = 'user' AND receiver_id = auth.uid())
        OR
        -- 广播消息所有人可见
        (receiver_type = 'broadcast')
        OR
        -- 群组消息（使用函数检查，避免递归）
        (receiver_type = 'group' AND public.is_group_member(receiver_id, auth.uid()))
        OR
        -- 管理员可以查看所有消息
        auth.jwt() ->> 'user_role' = 'admin'
    );

CREATE POLICY "users_can_send_messages" ON public.ak_messages
    FOR INSERT WITH CHECK (
        -- 用户只能以自己的身份发送
        (sender_type = 'user' AND sender_id = auth.uid())
        OR
        -- 管理员可以发送系统消息
        (sender_type = 'system' AND auth.jwt() ->> 'user_role' = 'admin')
    );

CREATE POLICY "users_can_update_own_messages" ON public.ak_messages
    FOR UPDATE USING (
        (sender_type = 'user' AND sender_id = auth.uid())
        OR
        auth.jwt() ->> 'user_role' = 'admin'
    );

CREATE POLICY "users_can_delete_own_messages" ON public.ak_messages
    FOR DELETE USING (
        (sender_type = 'user' AND sender_id = auth.uid())
        OR
        auth.jwt() ->> 'user_role' = 'admin'
    );

-- 5. 消息接收者策略
CREATE POLICY "users_can_view_own_recipients" ON public.ak_message_recipients
    FOR SELECT USING (
        user_id = auth.uid()
        OR
        auth.jwt() ->> 'user_role' = 'admin'
    );

CREATE POLICY "system_can_create_recipients" ON public.ak_message_recipients
    FOR INSERT WITH CHECK (
        user_id = auth.uid()
        OR
        auth.jwt() ->> 'user_role' = 'admin'
    );

CREATE POLICY "users_can_update_own_recipients" ON public.ak_message_recipients
    FOR UPDATE USING (
        user_id = auth.uid()
        OR
        auth.jwt() ->> 'user_role' = 'admin'
    );

-- 6. 消息模板策略
CREATE POLICY "users_can_view_templates" ON public.ak_message_templates
    FOR SELECT USING (
        is_public = true
        OR
        created_by = auth.uid()
        OR
        auth.jwt() ->> 'user_role' = 'admin'
    );

CREATE POLICY "users_can_create_templates" ON public.ak_message_templates
    FOR INSERT WITH CHECK (
        auth.role() = 'authenticated' AND created_by = auth.uid()
    );

CREATE POLICY "users_can_update_own_templates" ON public.ak_message_templates
    FOR UPDATE USING (
        created_by = auth.uid()
        OR
        auth.jwt() ->> 'user_role' = 'admin'
    );

CREATE POLICY "users_can_delete_own_templates" ON public.ak_message_templates
    FOR DELETE USING (
        created_by = auth.uid()
        OR
        auth.jwt() ->> 'user_role' = 'admin'
    );

-- 7. 用户偏好策略
CREATE POLICY "users_can_manage_own_preferences" ON public.ak_user_message_preferences
    FOR ALL USING (
        user_id = auth.uid()
        OR
        auth.jwt() ->> 'user_role' = 'admin'
    );

-- 8. 消息统计策略
CREATE POLICY "users_can_view_relevant_stats" ON public.ak_message_stats
    FOR SELECT USING (
        (entity_type = 'user' AND entity_id = auth.uid())
        OR
        auth.jwt() ->> 'user_role' = 'admin'
    );

CREATE POLICY "admins_can_update_stats" ON public.ak_message_stats
    FOR ALL USING (
        auth.jwt() ->> 'user_role' = 'admin'
    );

-- 验证策略创建结果
DO $$
DECLARE
    policy_count INTEGER;
    function_count INTEGER;
BEGIN
    RAISE NOTICE '🔍 验证策略重建结果';
    
    -- 检查策略数量
    SELECT COUNT(*) INTO policy_count
    FROM pg_policies 
    WHERE schemaname = 'public' 
    AND tablename IN ('ak_messages', 'ak_message_recipients', 'ak_message_groups', 
                     'ak_message_group_members', 'ak_message_templates', 
                     'ak_user_message_preferences', 'ak_message_stats', 'ak_message_types');
    
    -- 检查辅助函数
    SELECT COUNT(*) INTO function_count
    FROM information_schema.routines
    WHERE routine_schema = 'public'
    AND routine_name = 'is_group_member';
    
    RAISE NOTICE '📊 重建统计:';
    RAISE NOTICE '  - 策略数量: %', policy_count;
    RAISE NOTICE '  - 辅助函数: %', function_count;
    
    IF policy_count > 20 AND function_count > 0 THEN
        RAISE NOTICE '🎉 策略重建成功！递归问题已解决';
    ELSE
        RAISE NOTICE '⚠️ 重建可能不完整，请检查';
    END IF;
END $$;

-- 完成消息
SELECT 
    '✅ RLS策略递归问题已修复' as status,
    '使用了辅助函数和简化逻辑避免递归' as message;
