-- ====================================================
-- InsightReply 数据库 Schema (PostgreSQL)
-- 版本: v1.1
-- 更新: 新增 api_usage_logs, subscriptions, user_style_profiles 表
-- ====================================================

-- users 表：存储业务用户
CREATE TABLE IF NOT EXISTS users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255),
    subscription_tier VARCHAR(50) DEFAULT 'Free', -- Free, Pro, Premium
    identity_label VARCHAR(100), -- AI 创始人, SaaS Builder 等
    language_preference VARCHAR(10) DEFAULT 'auto', -- en, zh, auto
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- monitored_accounts 表：存储用户重点监控的 X 账号
CREATE TABLE IF NOT EXISTS monitored_accounts (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    x_account_id VARCHAR(255),
    x_handle VARCHAR(255) NOT NULL,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    UNIQUE (user_id, x_handle)
);

-- monitored_keywords 表：存储用户重点监控的关键词
CREATE TABLE IF NOT EXISTS monitored_keywords (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    keyword VARCHAR(255) NOT NULL,
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    UNIQUE (user_id, keyword)
);

-- tweets 表：共享的推文数据池，AI 评论生成的上下文
CREATE TABLE IF NOT EXISTS tweets (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    x_tweet_id VARCHAR(255) UNIQUE NOT NULL,
    author_id VARCHAR(255),
    author_handle VARCHAR(255),
    content TEXT NOT NULL,
    posted_at TIMESTAMP WITH TIME ZONE,
    like_count INTEGER DEFAULT 0,
    retweet_count INTEGER DEFAULT 0,
    reply_count INTEGER DEFAULT 0,
    heat_score FLOAT DEFAULT 0.0,
    crawl_queue VARCHAR(20) DEFAULT 'normal', -- high, normal, low (智能抓取频率)
    is_processed BOOLEAN DEFAULT FALSE,
    last_crawled_at TIMESTAMP WITH TIME ZONE, -- 上次抓取时间
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_tweets_x_tweet_id ON tweets(x_tweet_id);
CREATE INDEX IF NOT EXISTS idx_tweets_heat_score ON tweets(heat_score DESC);
CREATE INDEX IF NOT EXISTS idx_tweets_crawl_queue ON tweets(crawl_queue, last_crawled_at);

-- generated_replies 表：生成的 AI 评论记录
CREATE TABLE IF NOT EXISTS generated_replies (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    tweet_id UUID NOT NULL REFERENCES tweets(id) ON DELETE CASCADE,
    strategy_type VARCHAR(100) NOT NULL, -- cognitive_upgrade, contrarian, data_supplement, empathy, founder_exp
    content TEXT NOT NULL,
    status VARCHAR(50) DEFAULT 'draft', -- draft, copied, posted
    language VARCHAR(10) DEFAULT 'en', -- 生成语言
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_generated_replies_user_id ON generated_replies(user_id);
CREATE INDEX IF NOT EXISTS idx_generated_replies_tweet_id ON generated_replies(tweet_id);

-- reply_performance 表：针对已发布评论的效果数据回拨
CREATE TABLE IF NOT EXISTS reply_performance (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    reply_id UUID NOT NULL REFERENCES generated_replies(id) ON DELETE CASCADE,
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, -- 冗余字段，便于按用户维度查询
    like_count_increase INTEGER DEFAULT 0,
    reply_count_increase INTEGER DEFAULT 0,
    interaction_rate FLOAT DEFAULT 0.0,
    check_time TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_reply_performance_reply_id ON reply_performance(reply_id);
CREATE INDEX IF NOT EXISTS idx_reply_performance_user_id ON reply_performance(user_id);

-- ====================================================
-- 新增表 (v1.1)
-- ====================================================

-- api_usage_logs 表：记录 LLM API 调用量和成本
CREATE TABLE IF NOT EXISTS api_usage_logs (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    provider VARCHAR(50) NOT NULL, -- openai, anthropic, deepseek
    model VARCHAR(100) NOT NULL, -- gpt-4o-mini, claude-3.5-haiku 等
    prompt_tokens INTEGER DEFAULT 0,
    completion_tokens INTEGER DEFAULT 0,
    total_tokens INTEGER GENERATED ALWAYS AS (prompt_tokens + completion_tokens) STORED,
    cost_usd NUMERIC(10, 6) DEFAULT 0.0, -- 精确到 $0.000001
    endpoint VARCHAR(100), -- /ai/generate
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_api_usage_logs_user_id ON api_usage_logs(user_id);
CREATE INDEX IF NOT EXISTS idx_api_usage_logs_created_at ON api_usage_logs(created_at DESC);

-- subscriptions 表：用户订阅记录（支付历史）
CREATE TABLE IF NOT EXISTS subscriptions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    tier VARCHAR(50) NOT NULL, -- Pro, Premium
    stripe_subscription_id VARCHAR(255), -- Stripe 订阅 ID
    status VARCHAR(50) DEFAULT 'active', -- active, cancelled, past_due, expired
    started_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    expires_at TIMESTAMP WITH TIME ZONE,
    cancelled_at TIMESTAMP WITH TIME ZONE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_subscriptions_user_id ON subscriptions(user_id);
CREATE INDEX IF NOT EXISTS idx_subscriptions_status ON subscriptions(status);

-- user_style_profiles 表：用户风格画像（用于个性化 Prompt）
CREATE TABLE IF NOT EXISTS user_style_profiles (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID UNIQUE NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    top_strategies JSONB DEFAULT '[]', -- 最常选择的策略排序
    avg_reply_length INTEGER DEFAULT 200, -- 平均偏好回复长度
    high_engagement_keywords JSONB DEFAULT '[]', -- 高互动关键词
    tone_preference VARCHAR(100) DEFAULT 'professional', -- casual, professional, witty, provocative
    custom_prompt_suffix TEXT, -- 用户自定义的额外 Prompt 指令
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- crawl_snapshots 表：异常抓取时的 HTML 快照（排错用）
CREATE TABLE IF NOT EXISTS crawl_snapshots (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    url TEXT NOT NULL,
    http_status INTEGER,
    html_content TEXT,
    error_message TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX IF NOT EXISTS idx_crawl_snapshots_created_at ON crawl_snapshots(created_at DESC);

-- ====================================================
-- 新增表 (v1.2) — 用户可配置系统
-- ====================================================

-- user_product_profiles 表：用户的产品档案（用于生成与产品相关联的评论）
-- 设计原则：所有字段用户自定义，系统不做任何硬编码
CREATE TABLE IF NOT EXISTS user_product_profiles (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID UNIQUE NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    product_name VARCHAR(255),                    -- 产品名称 (如 "SwiftBiu")
    tagline TEXT,                                  -- 一句话介绍
    domain VARCHAR(255),                           -- 所属领域 (如 "AI Video Creation")
    key_features JSONB DEFAULT '[]',              -- 核心功能列表 ["视频生成", "多语言配音"]
    target_users TEXT,                             -- 目标用户描述
    product_url VARCHAR(500),                      -- 官网或商店链接
    competitors JSONB DEFAULT '[]',               -- 竞品名称列表 ["CapCut", "Descript"]
    relevance_keywords JSONB DEFAULT '[]',        -- 相关领域关键词 ["short video", "content creation", "AI dubbing"]
    custom_context TEXT,                           -- 用户自定义的额外上下文（自由文本，注入 Prompt）
    default_llm_provider VARCHAR(50),              -- 用户专属模型偏好: openai, anthropic, deepseek, gemini (覆盖系统默认)
    default_llm_model VARCHAR(100),                -- 例如: claude-3-5-haiku-latest
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- user_custom_strategies 表：用户自定义评论策略
-- 除系统内置的 5 种策略外，用户可以创建自己的策略模板
CREATE TABLE IF NOT EXISTS user_custom_strategies (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    strategy_key VARCHAR(100) NOT NULL,            -- 策略标识 (如 "builder_story")
    label VARCHAR(255) NOT NULL,                   -- 显示名称 (如 "创始人实战型")
    icon VARCHAR(10),                              -- Emoji 图标
    description TEXT,                              -- 策略描述（告诉 LLM 这种策略的写法）
    prompt_template TEXT,                          -- 自定义 Prompt 模板（可包含 {tweet_content} {product_name} 等变量）
    few_shot_examples JSONB DEFAULT '[]',          -- 自定义 Few-shot 示例
    is_active BOOLEAN DEFAULT TRUE,
    sort_order INTEGER DEFAULT 0,                  -- 排序权重
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    UNIQUE (user_id, strategy_key)
);

CREATE INDEX IF NOT EXISTS idx_user_custom_strategies_user_id ON user_custom_strategies(user_id);

-- competitor_monitors 表：竞品品牌监控（复用后端雷达，按品牌词自动抓取）
CREATE TABLE IF NOT EXISTS competitor_monitors (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    brand_name VARCHAR(255) NOT NULL,              -- 竞品品牌名
    x_handle VARCHAR(255),                         -- 竞品官方 X 账号 (可选)
    is_active BOOLEAN DEFAULT TRUE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    UNIQUE (user_id, brand_name)
);

CREATE INDEX IF NOT EXISTS idx_competitor_monitors_user_id ON competitor_monitors(user_id);

-- ====================================================
-- 触发器：自动更新 updated_at
-- ====================================================

CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ language 'plpgsql';

-- 为所有需要追踪更新时间的表添加触发器
DO $$ BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_users_modtime') THEN
    CREATE TRIGGER update_users_modtime
        BEFORE UPDATE ON users
        FOR EACH ROW
        EXECUTE FUNCTION update_modified_column();
  END IF;
END $$;

DO $$ BEGIN
  IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_user_style_profiles_modtime') THEN
    CREATE TRIGGER update_user_style_profiles_modtime
        BEFORE UPDATE ON user_style_profiles
        FOR EACH ROW
        EXECUTE FUNCTION update_modified_column();
  END IF;
END $$;
