ALTER TABLE script_analyses
    ADD COLUMN analysis_result jsonb NOT NULL DEFAULT '{}'::jsonb,
    ADD COLUMN analysis_status varchar(20) NOT NULL DEFAULT 'idle',
    ADD COLUMN analysis_message text;

ALTER TABLE script_analyses
    ADD CONSTRAINT script_analyses_status_check
    CHECK (analysis_status IN ('idle', 'queued', 'running', 'succeeded', 'failed'));

CREATE TABLE script_analysis_characters (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    script_analysis_id uuid NOT NULL REFERENCES script_analyses(id) ON DELETE CASCADE,
    name citext NOT NULL,
    faction varchar(20) NOT NULL,
    biography text NOT NULL DEFAULT '',
    motivation text NOT NULL DEFAULT '',
    relationship text NOT NULL DEFAULT '',
    sort_order integer NOT NULL DEFAULT 0,
    created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT script_analysis_characters_faction_check CHECK (faction IN ('正派', '反派', '中立派')),
    CONSTRAINT script_analysis_characters_name_unique UNIQUE (script_analysis_id, name)
);

CREATE INDEX idx_script_analysis_characters_analysis
    ON script_analysis_characters(script_analysis_id, sort_order);
CREATE TRIGGER script_analysis_characters_updated_at
    BEFORE UPDATE ON script_analysis_characters
    FOR EACH ROW EXECUTE FUNCTION set_updated_at();

ALTER TABLE generation_tasks
    ADD COLUMN script_analysis_id uuid REFERENCES script_analyses(id) ON DELETE CASCADE;

ALTER TABLE generation_tasks
    DROP CONSTRAINT generation_tasks_task_type_check;
ALTER TABLE generation_tasks
    ADD CONSTRAINT generation_tasks_task_type_check
    CHECK (task_type IN ('prompt_reverse', 'image_generation', 'video_generation', 'script_analysis'));

CREATE INDEX idx_generation_tasks_script_analysis
    ON generation_tasks(script_analysis_id, created_at DESC)
    WHERE script_analysis_id IS NOT NULL;
CREATE UNIQUE INDEX uq_script_analysis_active_task
    ON generation_tasks(script_analysis_id)
    WHERE script_analysis_id IS NOT NULL
      AND status IN ('pending_submission', 'submitting', 'submit_unknown', 'submitted', 'processing', 'result_ready', 'downloading', 'cancel_requested');

INSERT INTO prompts (id, name, type, content, scope, owner_user_id)
VALUES (
    '2eb481cf-4a8f-4da4-a70e-ea977739c8d1',
    '默认剧本分析提示词',
    '剧本分析',
    $prompt$你是一名资深短剧策划、编剧和商业化内容分析师。请严格依据用户提供的剧本原文进行结构化分析，不得把推测写成原文事实，不得编造原文不存在的关键人物、情节或台词。信息不足时使用空字符串或空数组。

分析目标：
1. 标签：分别提取短剧题材、风格、受众、情绪等短剧标签，以及适合山水景区、古镇景区、主题乐园、文博场馆、商业街区等文旅或商业落地场景的适用场景标签。只输出与剧本确实匹配的标签。
2. 核心看点与卖点：用一句话总结核心看点、卖点、爽点或痛点，并列出具体看点及其类型。
3. 剧情结构：输出短剧梗概、故事大纲、情绪大纲、分集大纲和人物小传。人物必须覆盖剧本中具有明确身份或剧情作用的正派、反派和中立人物；faction 只能是“正派”“反派”“中立派”。同一人物只返回一次。
4. 第一集黄金三秒：分别给出开篇第一个画面或场景、第一句台词，以及通过悬念前置、激烈冲突、视觉奇观等方式瞬间抓住观众的设计。若原稿开篇不够强，需要明确说明问题并给出不改变核心剧情的优化建议；第一句台词不得冒充原文台词，建议台词需明确标为建议。
5. 单集钩子：输出第1至第10集逐集钩子。原文无法识别某一集时保留该集编号并说明信息不足，不得虚构剧情。第10集除逐集钩子外，再提供3至5个付费卡点候选，每个候选需说明钩子类型、卡点内容和付费吸引力。$prompt$,
    'system',
    NULL
)
ON CONFLICT (id) DO UPDATE SET
    name = EXCLUDED.name,
    type = EXCLUDED.type,
    content = EXCLUDED.content,
    scope = EXCLUDED.scope,
    owner_user_id = EXCLUDED.owner_user_id,
    deleted_at = NULL,
    updated_at = CURRENT_TIMESTAMP;
