-- ===================================================================
-- 消息系统表结构更新脚本
-- 用于在表已存在的情况下，确保数据结构完整和数据正确
-- ===================================================================

-- 1. 更新消息类型数据（如果表已存在）
-- 使用 INSERT ... ON CONFLICT 来安全地插入或更新数据

INSERT INTO ak_message_types (code, name, description, icon, color, priority, is_system, auto_read_timeout, retention_days) 
VALUES
    ('system', '系统消息', '系统自动发送的重要通知', 'system', '#2196F3', 100, true, 0, 90),
    ('device', '设备消息', '设备发送的状态和数据消息', 'device', '#FF5722', 80, true, 300, 7),
    ('training', '训练提醒', '训练计划和完成情况提醒', 'training', '#4CAF50', 70, true, 0, 30),
    ('social', '社交消息', '用户间的社交互动消息', 'social', '#E91E63', 60, false, 0, 30),
    ('assignment', '作业通知', '作业发布、截止、批改通知', 'assignment', '#FF9800', 75, true, 0, 60),
    ('achievement', '成就通知', '积分、成就、奖励通知', 'achievement', '#FFC107', 50, true, 3600, 90),
    ('chat', '即时消息', '用户间的实时聊天消息', 'chat', '#9C27B0', 90, false, 0, 7),
    ('announcement', '公告通知', '系统公告和重要通知', 'announcement', '#3F51B5', 95, true, 0, 180),
    ('reminder', '提醒消息', '定时提醒和事件提醒', 'reminder', '#00BCD4', 65, true, 0, 14),
    ('alert', '警报消息', '紧急情况和异常状态警报', 'alert', '#F44336', 99, true, 0, 30)
ON CONFLICT (code) DO UPDATE SET
    name = EXCLUDED.name,
    description = EXCLUDED.description,
    icon = EXCLUDED.icon,
    color = EXCLUDED.color,
    priority = EXCLUDED.priority,
    is_system = EXCLUDED.is_system,
    auto_read_timeout = EXCLUDED.auto_read_timeout,
    retention_days = EXCLUDED.retention_days,
    updated_at = now();

-- 2. 检查并创建缺失的列（如果需要）
-- 注意：这些语句只在相应列不存在时执行

-- 为 ak_message_types 添加可能缺失的列
ALTER TABLE ak_message_types ADD COLUMN IF NOT EXISTS icon VARCHAR(64);
ALTER TABLE ak_message_types ADD COLUMN IF NOT EXISTS color VARCHAR(16);
ALTER TABLE ak_message_types ADD COLUMN IF NOT EXISTS priority INT DEFAULT 0;
ALTER TABLE ak_message_types ADD COLUMN IF NOT EXISTS auto_read_timeout INT;
ALTER TABLE ak_message_types ADD COLUMN IF NOT EXISTS retention_days INT DEFAULT 30;

-- 3. 创建缺失的索引（如果需要）
-- 使用 IF NOT EXISTS 避免重复创建

-- ak_messages 表的索引
CREATE INDEX IF NOT EXISTS idx_ak_messages_type ON ak_messages(message_type_id);
CREATE INDEX IF NOT EXISTS idx_ak_messages_sender ON ak_messages(sender_type, sender_id);
CREATE INDEX IF NOT EXISTS idx_ak_messages_receiver ON ak_messages(receiver_type, receiver_id);
CREATE INDEX IF NOT EXISTS idx_ak_messages_status ON ak_messages(status);
CREATE INDEX IF NOT EXISTS idx_ak_messages_created_at ON ak_messages(created_at);
CREATE INDEX IF NOT EXISTS idx_ak_messages_scheduled_at ON ak_messages(scheduled_at);
CREATE INDEX IF NOT EXISTS idx_ak_messages_urgent ON ak_messages(is_urgent) WHERE is_urgent = true;

-- ak_message_recipients 表的索引
CREATE INDEX IF NOT EXISTS idx_ak_message_recipients_message ON ak_message_recipients(message_id);
CREATE INDEX IF NOT EXISTS idx_ak_message_recipients_receiver ON ak_message_recipients(receiver_type, receiver_id);
CREATE INDEX IF NOT EXISTS idx_ak_message_recipients_status ON ak_message_recipients(status);
CREATE INDEX IF NOT EXISTS idx_ak_message_recipients_unread ON ak_message_recipients(receiver_type, receiver_id, status) WHERE status = 'unread';

-- ak_message_groups 表的索引（如果表存在）
CREATE INDEX IF NOT EXISTS idx_ak_message_groups_active ON ak_message_groups(is_active);
CREATE INDEX IF NOT EXISTS idx_ak_message_groups_type ON ak_message_groups(group_type);

-- ak_message_group_members 表的索引（如果表存在）
CREATE INDEX IF NOT EXISTS idx_ak_message_group_members_group ON ak_message_group_members(group_id);
CREATE INDEX IF NOT EXISTS idx_ak_message_group_members_user ON ak_message_group_members(user_id);
CREATE INDEX IF NOT EXISTS idx_ak_message_group_members_active ON ak_message_group_members(group_id, is_active);

-- 4. 创建或替换有用的视图和函数

-- 消息统计视图
CREATE OR REPLACE VIEW v_message_stats AS
SELECT 
    receiver_type,
    receiver_id,
    COUNT(*) as total_messages,
    COUNT(CASE WHEN mr.status = 'unread' THEN 1 END) as unread_messages,
    COUNT(CASE WHEN m.is_urgent = true AND mr.status = 'unread' THEN 1 END) as urgent_unread,
    MAX(m.created_at) as last_message_time
FROM ak_messages m
JOIN ak_message_recipients mr ON m.id = mr.message_id
WHERE m.is_deleted = false AND mr.is_deleted = false
GROUP BY receiver_type, receiver_id;

-- 更新时间触发器函数
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = now();
    RETURN NEW;
END;
$$ language 'plpgsql';

-- 获取用户消息统计的函数
CREATE OR REPLACE FUNCTION get_user_message_stats(user_id_param TEXT)
RETURNS TABLE(
    total_messages BIGINT,
    unread_messages BIGINT,
    urgent_unread BIGINT,
    read_messages BIGINT
) AS $$
BEGIN
    RETURN QUERY
    SELECT 
        COALESCE(vs.total_messages, 0) as total_messages,
        COALESCE(vs.unread_messages, 0) as unread_messages,
        COALESCE(vs.urgent_unread, 0) as urgent_unread,
        COALESCE(vs.total_messages - vs.unread_messages, 0) as read_messages
    FROM v_message_stats vs
    WHERE vs.receiver_type = 'user' AND vs.receiver_id = user_id_param
    UNION ALL
    SELECT 0::BIGINT, 0::BIGINT, 0::BIGINT, 0::BIGINT
    WHERE NOT EXISTS (
        SELECT 1 FROM v_message_stats vs 
        WHERE vs.receiver_type = 'user' AND vs.receiver_id = user_id_param
    )
    LIMIT 1;
END;
$$ LANGUAGE plpgsql;

-- 批量标记消息为已读的函数
CREATE OR REPLACE FUNCTION mark_messages_as_read(
    message_ids_param UUID[],
    user_id_param TEXT
)
RETURNS INTEGER AS $$
DECLARE
    affected_count INTEGER;
BEGIN
    UPDATE ak_message_recipients 
    SET 
        status = 'read',
        read_at = now(),
        updated_at = now()
    WHERE 
        message_id = ANY(message_ids_param)
        AND receiver_type = 'user'
        AND receiver_id = user_id_param
        AND status = 'unread';
    
    GET DIAGNOSTICS affected_count = ROW_COUNT;
    RETURN affected_count;
END;
$$ LANGUAGE plpgsql;

-- 批量删除消息的函数
CREATE OR REPLACE FUNCTION delete_messages_for_user(
    message_ids_param UUID[],
    user_id_param TEXT
)
RETURNS INTEGER AS $$
DECLARE
    affected_count INTEGER;
BEGIN
    UPDATE ak_message_recipients 
    SET 
        status = 'deleted',
        deleted_at = now(),
        is_deleted = true,
        updated_at = now()
    WHERE 
        message_id = ANY(message_ids_param)
        AND receiver_type = 'user'
        AND receiver_id = user_id_param
        AND is_deleted = false;
    
    GET DIAGNOSTICS affected_count = ROW_COUNT;
    RETURN affected_count;
END;
$$ LANGUAGE plpgsql;

-- 5. 验证数据完整性
-- 显示最终的消息类型配置
SELECT 
    code, 
    name, 
    priority, 
    is_system, 
    is_active,
    retention_days,
    icon,
    color
FROM ak_message_types 
ORDER BY priority DESC, code;
