-- ============================================================================
-- Echo (回声) - 初始数据库 Schema 迁移脚本
-- 版本: 202601120001
-- 创建日期: 2026-01-12
-- ============================================================================

-- 启用 UUID 扩展
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- ============================================================================
-- 第一部分: 公共函数定义
-- ============================================================================

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

-- ============================================================================
-- 第二部分: 表创建（按依赖顺序）
-- ============================================================================

-- ---------------------------------------------------------------------------
-- 2.1 users - 用户表
-- ---------------------------------------------------------------------------
CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email VARCHAR(255) UNIQUE NOT NULL,
    google_id VARCHAR(255) UNIQUE,
    avatar_url TEXT,
    language VARCHAR(10) DEFAULT 'zh-CN',
    subscription_status VARCHAR(20) DEFAULT 'free',
    subscription_expires_at TIMESTAMP WITH TIME ZONE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 用户表索引
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_google_id ON users(google_id);

-- ---------------------------------------------------------------------------
-- 2.2 agents - 智能体表
-- ---------------------------------------------------------------------------
CREATE TABLE agents (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    name VARCHAR(100) NOT NULL,
    personality JSONB NOT NULL DEFAULT '{}',
    background TEXT,
    avatar_url TEXT,
    is_custom BOOLEAN DEFAULT FALSE,
    is_default BOOLEAN DEFAULT FALSE,
    language VARCHAR(10) DEFAULT 'zh-CN',
    system_prompt TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 智能体表索引
CREATE INDEX idx_agents_user_id ON agents(user_id);
CREATE INDEX idx_agents_default ON agents(user_id, is_default) WHERE is_custom = FALSE;

-- ---------------------------------------------------------------------------
-- 2.3 onboarding_answers - 初始问题回答表
-- ---------------------------------------------------------------------------
CREATE TABLE onboarding_answers (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    question_1 TEXT NOT NULL,
    question_2 TEXT NOT NULL,
    question_3 TEXT NOT NULL,
    question_4 TEXT NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 初始问题回答表索引
CREATE INDEX idx_onboarding_answers_user_id ON onboarding_answers(user_id);

-- ---------------------------------------------------------------------------
-- 2.4 letters - 信件表
-- ---------------------------------------------------------------------------
CREATE TABLE letters (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    agent_id UUID NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
    content TEXT NOT NULL,
    ai_reply TEXT,
    status VARCHAR(20) DEFAULT 'draft',
    scheduled_at TIMESTAMP WITH TIME ZONE,
    replied_at TIMESTAMP WITH TIME ZONE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 信件表索引
CREATE INDEX idx_letters_user_id ON letters(user_id);
CREATE INDEX idx_letters_agent_id ON letters(agent_id);
CREATE INDEX idx_letters_status ON letters(status);
CREATE INDEX idx_letters_scheduled ON letters(status, scheduled_at)
    WHERE status = 'pending';

-- ---------------------------------------------------------------------------
-- 2.5 stamp_definitions - 邮票定义表
-- ---------------------------------------------------------------------------
CREATE TABLE stamp_definitions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    code VARCHAR(50) UNIQUE NOT NULL,
    name VARCHAR(100) NOT NULL,
    description TEXT,
    stamp_type VARCHAR(30) NOT NULL,
    rarity VARCHAR(20) DEFAULT 'common',
    image_url TEXT NOT NULL,
    valid_from TIMESTAMP WITH TIME ZONE,
    valid_until TIMESTAMP WITH TIME ZONE,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 邮票定义表索引
CREATE INDEX idx_stamp_definitions_code ON stamp_definitions(code);
CREATE INDEX idx_stamp_definitions_type ON stamp_definitions(stamp_type);
CREATE INDEX idx_stamp_definitions_active ON stamp_definitions(is_active);

-- ---------------------------------------------------------------------------
-- 2.6 user_stamps - 用户邮票表
-- ---------------------------------------------------------------------------
CREATE TABLE user_stamps (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    stamp_def_id UUID NOT NULL REFERENCES stamp_definitions(id),
    source VARCHAR(30) NOT NULL,
    letter_id UUID REFERENCES letters(id),
    obtained_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    used_at TIMESTAMP WITH TIME ZONE
);

-- 用户邮票表索引
CREATE INDEX idx_user_stamps_user_id ON user_stamps(user_id);
CREATE INDEX idx_user_stamps_letter_id ON user_stamps(letter_id);
CREATE INDEX idx_user_stamps_unused ON user_stamps(user_id, used_at)
    WHERE used_at IS NULL;

-- ---------------------------------------------------------------------------
-- 2.7 growth_tags - 成长标签表
-- ---------------------------------------------------------------------------
CREATE TABLE growth_tags (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    letter_id UUID NOT NULL REFERENCES letters(id) ON DELETE CASCADE,
    mood_tags TEXT[] DEFAULT '{}',
    topic_tags TEXT[] DEFAULT '{}',
    behavior_tags TEXT[] DEFAULT '{}',
    sentiment_score DECIMAL(3,2),
    keywords TEXT[] DEFAULT '{}',
    ai_analysis TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 成长标签表索引
CREATE INDEX idx_growth_tags_user_id ON growth_tags(user_id);
CREATE INDEX idx_growth_tags_letter_id ON growth_tags(letter_id);
CREATE INDEX idx_growth_tags_mood ON growth_tags USING GIN (mood_tags);
CREATE INDEX idx_growth_tags_topic ON growth_tags USING GIN (topic_tags);

-- ---------------------------------------------------------------------------
-- 2.8 milestones - 里程碑定义表
-- ---------------------------------------------------------------------------
CREATE TABLE milestones (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    code VARCHAR(50) UNIQUE NOT NULL,
    name VARCHAR(100) NOT NULL,
    description TEXT,
    condition_type VARCHAR(30) NOT NULL,
    condition_value INTEGER NOT NULL,
    reward_stamp_def_id UUID REFERENCES stamp_definitions(id),
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- 里程碑定义表索引
CREATE INDEX idx_milestones_code ON milestones(code);
CREATE INDEX idx_milestones_active ON milestones(is_active);

-- ---------------------------------------------------------------------------
-- 2.9 achievements - 用户成就表
-- ---------------------------------------------------------------------------
CREATE TABLE achievements (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    milestone_id UUID NOT NULL REFERENCES milestones(id),
    achieved_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    notification_sent BOOLEAN DEFAULT FALSE,
    UNIQUE(user_id, milestone_id)
);

-- 用户成就表索引
CREATE INDEX idx_achievements_user_id ON achievements(user_id);
CREATE INDEX idx_achievements_milestone_id ON achievements(milestone_id);

-- ---------------------------------------------------------------------------
-- 2.10 daily_stats - 每日统计表
-- ---------------------------------------------------------------------------
CREATE TABLE daily_stats (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    stat_date DATE NOT NULL,
    letters_sent INTEGER DEFAULT 0,
    stamps_used INTEGER DEFAULT 0,
    stamps_granted INTEGER DEFAULT 0,
    last_active_at TIMESTAMP WITH TIME ZONE,
    UNIQUE(user_id, stat_date)
);

-- 每日统计表索引
CREATE INDEX idx_daily_stats_user_date ON daily_stats(user_id, stat_date);

-- ============================================================================
-- 第三部分: 自动更新时间戳触发器
-- ============================================================================

CREATE TRIGGER update_users_updated_at
    BEFORE UPDATE ON users
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_agents_updated_at
    BEFORE UPDATE ON agents
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_letters_updated_at
    BEFORE UPDATE ON letters
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

-- ============================================================================
-- 第四部分: Row Level Security (RLS) 策略
-- ============================================================================

-- 4.1 users - 用户表 RLS
ALTER TABLE users ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can view own profile" ON users
    FOR SELECT USING (auth.uid() = id);

CREATE POLICY "Users can update own profile" ON users
    FOR UPDATE USING (auth.uid() = id);

-- 4.2 agents - 智能体表 RLS
ALTER TABLE agents ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can view own agents" ON agents
    FOR SELECT USING (auth.uid() = user_id);

CREATE POLICY "Users can create agents" ON agents
    FOR INSERT WITH CHECK (auth.uid() = user_id);

CREATE POLICY "Users can update own agents" ON agents
    FOR UPDATE USING (auth.uid() = user_id);

CREATE POLICY "Users can delete own agents" ON agents
    FOR DELETE USING (auth.uid() = user_id);

-- 4.3 onboarding_answers - 初始问题回答表 RLS
ALTER TABLE onboarding_answers ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can view own onboarding answers" ON onboarding_answers
    FOR SELECT USING (auth.uid() = user_id);

CREATE POLICY "Users can create onboarding answers" ON onboarding_answers
    FOR INSERT WITH CHECK (auth.uid() = user_id);

CREATE POLICY "Users can update own onboarding answers" ON onboarding_answers
    FOR UPDATE USING (auth.uid() = user_id);

-- 4.4 letters - 信件表 RLS
ALTER TABLE letters ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can view own letters" ON letters
    FOR SELECT USING (auth.uid() = user_id);

CREATE POLICY "Users can create letters" ON letters
    FOR INSERT WITH CHECK (auth.uid() = user_id);

CREATE POLICY "Users can update own letters" ON letters
    FOR UPDATE USING (auth.uid() = user_id);

CREATE POLICY "Users can delete own letters" ON letters
    FOR DELETE USING (auth.uid() = user_id);

-- 4.5 stamp_definitions - 邮票定义表 RLS（公开查询）
ALTER TABLE stamp_definitions ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Anyone can view stamp definitions" ON stamp_definitions
    FOR SELECT USING (true);

-- 4.6 user_stamps - 用户邮票表 RLS
ALTER TABLE user_stamps ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can view own stamps" ON user_stamps
    FOR SELECT USING (auth.uid() = user_id);

CREATE POLICY "System can update user stamps" ON user_stamps
    FOR UPDATE USING (auth.role() = 'service_role');

CREATE POLICY "System can insert user stamps" ON user_stamps
    FOR INSERT WITH CHECK (auth.role() = 'service_role');

-- 4.7 growth_tags - 成长标签表 RLS
ALTER TABLE growth_tags ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can view own growth tags" ON growth_tags
    FOR SELECT USING (auth.uid() = user_id);

CREATE POLICY "System can create growth tags" ON growth_tags
    FOR INSERT WITH CHECK (auth.role() = 'service_role');

CREATE POLICY "System can update growth tags" ON growth_tags
    FOR UPDATE USING (auth.role() = 'service_role');

-- 4.8 milestones - 里程碑定义表 RLS（公开查询）
ALTER TABLE milestones ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Anyone can view milestones" ON milestones
    FOR SELECT USING (true);

-- 4.9 achievements - 用户成就表 RLS
ALTER TABLE achievements ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can view own achievements" ON achievements
    FOR SELECT USING (auth.uid() = user_id);

CREATE POLICY "System can create achievements" ON achievements
    FOR INSERT WITH CHECK (auth.role() = 'service_role');

-- 4.10 daily_stats - 每日统计表 RLS
ALTER TABLE daily_stats ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can view own daily stats" ON daily_stats
    FOR SELECT USING (auth.uid() = user_id);

CREATE POLICY "System can update daily stats" ON daily_stats
    FOR UPDATE USING (auth.role() = 'service_role');

CREATE POLICY "System can insert daily stats" ON daily_stats
    FOR INSERT WITH CHECK (auth.role() = 'service_role');

-- ============================================================================
-- 第五部分: 初始数据插入
-- ============================================================================

-- 5.1 邮票定义初始数据
INSERT INTO stamp_definitions (code, name, description, stamp_type, rarity, image_url, is_active) VALUES
('daily_default', '每日邮票', '每日自动发放的基础邮票', 'daily', 'common', '/stamps/daily.png', TRUE),
('welcome', '初遇回声', '完成注册，获得的第一个成就', 'achievement', 'rare', '/stamps/welcome.png', TRUE),
('first_letter', '第一封信', '成功发送第一封信件', 'achievement', 'rare', '/stamps/first_letter.png', TRUE),
('week_streak', '持续对话', '连续 7 天写信', 'achievement', 'epic', '/stamps/week_streak.png', TRUE),
('month_streak', '一月相伴', '连续 30 天写信', 'achievement', 'legendary', '/stamps/month_streak.png', TRUE),
('spring_2025', '春日限定 2025', '2025 春季活动限定邮票', 'limited', 'epic', '/stamps/spring_2025.png', TRUE),
('collector_10', '集邮家', '收集 10 种不同邮票', 'achievement', 'rare', '/stamps/collector_10.png', TRUE),
('collector_50', '邮票猎人', '收集 50 种不同邮票', 'achievement', 'epic', '/stamps/collector_50.png', TRUE);

-- 5.2 里程碑定义初始数据
INSERT INTO milestones (code, name, description, condition_type, condition_value, reward_stamp_def_id, is_active) VALUES
('welcome', '初遇回声', '完成注册，开启回声之旅', 'registration', 1, (SELECT id FROM stamp_definitions WHERE code = 'welcome'), TRUE),
('first_letter', '第一封信', '成功发送第一封信给未来的自己', 'letter_count', 1, (SELECT id FROM stamp_definitions WHERE code = 'first_letter'), TRUE),
('week_streak', '持续对话', '连续 7 天写信', 'consecutive_days', 7, (SELECT id FROM stamp_definitions WHERE code = 'week_streak'), TRUE),
('month_streak', '一月相伴', '连续 30 天写信', 'consecutive_days', 30, (SELECT id FROM stamp_definitions WHERE code = 'month_streak'), TRUE),
('letters_10', '十封信', '累计发送 10 封信', 'total_letters', 10, NULL, TRUE),
('letters_50', '五十封信', '累计发送 50 封信', 'total_letters', 50, NULL, TRUE),
('letters_100', '百封信', '累计发送 100 封信', 'total_letters', 100, NULL, TRUE),
('collector_10', '集邮家初级', '收集 10 种不同邮票', 'unique_stamps', 10, (SELECT id FROM stamp_definitions WHERE code = 'collector_10'), TRUE),
('collector_50', '集邮家高级', '收集 50 种不同邮票', 'unique_stamps', 50, (SELECT id FROM stamp_definitions WHERE code = 'collector_50'), TRUE);

-- ============================================================================
-- 迁移完成
-- ============================================================================
