CREATE TABLE IF NOT EXISTS tenants (
    id BIGINT NOT NULL,
    name VARCHAR(100) NOT NULL,
    slug VARCHAR(50) NOT NULL,
    plan VARCHAR(20) NOT NULL DEFAULT 'free',
    status TINYINT NOT NULL DEFAULT 1,
    credits DECIMAL(18, 4) NOT NULL DEFAULT 0,
    frozen_credits DECIMAL(18, 4) NOT NULL DEFAULT 0,
    suspended_at TIMESTAMP,
    suspended_by BIGINT,
    suspended_reason VARCHAR(500),
    notes VARCHAR(1000),
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP,
    PRIMARY KEY (id),
    UNIQUE (slug)
);

CREATE TABLE IF NOT EXISTS users (
    id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100) NOT NULL,
    phone VARCHAR(20),
    avatar_url VARCHAR(500),
    password_hash VARCHAR(255) NOT NULL,
    role VARCHAR(20) NOT NULL DEFAULT 'member',
    status TINYINT NOT NULL DEFAULT 1,
    last_login_at TIMESTAMP,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP,
    PRIMARY KEY (id),
    UNIQUE (email),
    UNIQUE (username, tenant_id)
);

CREATE TABLE IF NOT EXISTS tenant_members (
    id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    user_id BIGINT NOT NULL,
    role VARCHAR(20) NOT NULL DEFAULT 'member',
    position VARCHAR(100),
    joined_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    UNIQUE (tenant_id, user_id)
);

CREATE TABLE IF NOT EXISTS projects (
    id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    user_id BIGINT NOT NULL,
    name VARCHAR(200) NOT NULL,
    description CLOB,
    status VARCHAR(20) NOT NULL DEFAULT 'draft',
    style VARCHAR(50),
    aspect_ratio VARCHAR(20),
    resolution VARCHAR(20),
    cover_key VARCHAR(500),
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS project_assets (
    id BIGINT NOT NULL,
    project_id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    name VARCHAR(255) NOT NULL,
    original_name VARCHAR(255) NOT NULL,
    asset_type VARCHAR(50) NOT NULL DEFAULT 'other',
    mime_type VARCHAR(100),
    file_size BIGINT,
    tos_key VARCHAR(500) NOT NULL,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS outlines (
    id BIGINT NOT NULL,
    project_id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    title VARCHAR(255),
    genre VARCHAR(100),
    episode_count INT,
    synopsis CLOB,
    raw_json CLOB,
    status VARCHAR(32) NOT NULL DEFAULT 'draft',
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS episodes (
    id BIGINT NOT NULL,
    outline_id BIGINT,
    project_id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    episode_number INT NOT NULL,
    title VARCHAR(255),
    summary CLOB,
    script CLOB,
    status VARCHAR(32) NOT NULL DEFAULT 'draft',
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS characters (
    id BIGINT NOT NULL,
    project_id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    name VARCHAR(100) NOT NULL,
    role_type VARCHAR(50),
    gender VARCHAR(20),
    age VARCHAR(50),
    personality CLOB,
    background CLOB,
    costume CLOB,
    visual_hint CLOB,
    image_prompt CLOB,
    image_url VARCHAR(1024),
    image_tos_key VARCHAR(512),
    front_image_url VARCHAR(1024),
    front_image_tos_key VARCHAR(512),
    side_image_url VARCHAR(1024),
    side_image_tos_key VARCHAR(512),
    back_image_url VARCHAR(1024),
    back_image_tos_key VARCHAR(512),
    status VARCHAR(32) NOT NULL DEFAULT 'draft',
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS character_states (
    id BIGINT NOT NULL,
    project_id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    character_id BIGINT NOT NULL,
    name VARCHAR(128) NOT NULL,
    state_type VARCHAR(32) DEFAULT 'costume',
    description CLOB,
    prompt CLOB,
    reference_image_key VARCHAR(512),
    image_url VARCHAR(1024),
    image_tos_key VARCHAR(512),
    status VARCHAR(32) NOT NULL DEFAULT 'draft',
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS scenes (
    id BIGINT NOT NULL,
    project_id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    name VARCHAR(120) NOT NULL,
    scene_type VARCHAR(50),
    description CLOB,
    image_prompt CLOB,
    image_url VARCHAR(1024),
    image_tos_key VARCHAR(512),
    status VARCHAR(32) NOT NULL DEFAULT 'draft',
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS storyboards (
    id BIGINT NOT NULL,
    project_id BIGINT NOT NULL,
    episode_id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    sequence_num INT NOT NULL,
    scene_number VARCHAR(50),
    short_description VARCHAR(255),
    detailed_description CLOB,
    characters CLOB,
    dialogues CLOB,
    camera_direction CLOB,
    composition_guide CLOB,
    duration_seconds INT,
    motion_script CLOB,
    start_frame_prompt CLOB,
    end_frame_prompt CLOB,
    scene_ref VARCHAR(255),
    video_prompt CLOB,
    notes CLOB,
    character_image_keys CLOB,
    scene_image_key VARCHAR(512),
    prop_image_keys CLOB,
    style_image_key VARCHAR(512),
    status VARCHAR(32) NOT NULL DEFAULT 'draft',
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE INDEX IF NOT EXISTS idx_outlines_project ON outlines (project_id, tenant_id);
CREATE INDEX IF NOT EXISTS idx_episodes_project ON episodes (project_id, tenant_id);
CREATE INDEX IF NOT EXISTS idx_characters_project ON characters (project_id, tenant_id);
CREATE INDEX IF NOT EXISTS idx_scenes_project ON scenes (project_id, tenant_id);
CREATE INDEX IF NOT EXISTS idx_storyboards_episode ON storyboards (episode_id, tenant_id);

CREATE TABLE IF NOT EXISTS shot_assets (
    id BIGINT NOT NULL,
    storyboard_id BIGINT NOT NULL,
    project_id BIGINT,
    episode_id BIGINT,
    tenant_id BIGINT NOT NULL,
    asset_type VARCHAR(32) NOT NULL,
    tos_key VARCHAR(512),
    external_url VARCHAR(1024),
    source_task_id BIGINT,
    prompt CLOB,
    model_provider VARCHAR(64),
    model_id VARCHAR(128),
    asset_version INT NOT NULL DEFAULT 1,
    characters CLOB,
    meta_json CLOB,
    error_message CLOB,
    status VARCHAR(32) NOT NULL DEFAULT 'pending',
    is_active TINYINT NOT NULL DEFAULT 1,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE INDEX IF NOT EXISTS idx_shot_assets_storyboard ON shot_assets (storyboard_id, tenant_id);
CREATE INDEX IF NOT EXISTS idx_shot_assets_project ON shot_assets (project_id, tenant_id);
CREATE INDEX IF NOT EXISTS idx_shot_assets_task ON shot_assets (source_task_id);

CREATE TABLE IF NOT EXISTS tenant_balances (
    id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    balance DECIMAL(18, 4) NOT NULL DEFAULT 0,
    total_recharged DECIMAL(18, 4) NOT NULL DEFAULT 0,
    total_spent DECIMAL(18, 4) NOT NULL DEFAULT 0,
    version INT NOT NULL DEFAULT 0,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    UNIQUE (tenant_id)
);

CREATE TABLE IF NOT EXISTS billing_records (
    id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    project_id BIGINT,
    user_id BIGINT,
    created_by_admin_id BIGINT,
    operation VARCHAR(64) NOT NULL,
    modality VARCHAR(16),
    model_provider VARCHAR(64),
    model_id VARCHAR(128),
    model_name VARCHAR(128),
    unit_count INT,
    success BOOLEAN,
    billing_meta CLOB,
    credits DECIMAL(18, 4) NOT NULL DEFAULT 0,
    billing_mode VARCHAR(16) NOT NULL DEFAULT 'SOFT',
    ref_id VARCHAR(128),
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS system_settings (
    id BIGINT NOT NULL,
    setting_key VARCHAR(128) NOT NULL,
    setting_value CLOB,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_by BIGINT,
    PRIMARY KEY (id),
    UNIQUE (setting_key)
);

CREATE TABLE IF NOT EXISTS ai_tasks (
    id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    project_id BIGINT NOT NULL,
    episode_id BIGINT,
    storyboard_id BIGINT,
    task_type VARCHAR(64) NOT NULL,
    external_task_id VARCHAR(255),
    status VARCHAR(32) NOT NULL DEFAULT 'pending',
    input_image_key VARCHAR(512),
    prompt CLOB,
    result_video_url VARCHAR(1024),
    result_tos_key VARCHAR(512),
    error_message CLOB,
    character_image_key VARCHAR(512),
    character_image_keys CLOB,
    scene_image_key VARCHAR(512),
    prop_image_keys CLOB,
    style_image_key VARCHAR(512),
    user_prompt CLOB,
    video_duration INT,
    video_ratio VARCHAR(10),
    generate_audio BOOLEAN NOT NULL DEFAULT FALSE,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE INDEX IF NOT EXISTS idx_ai_tasks_tenant_project ON ai_tasks (tenant_id, project_id);
CREATE INDEX IF NOT EXISTS idx_ai_tasks_episode ON ai_tasks (episode_id);
CREATE INDEX IF NOT EXISTS idx_ai_tasks_external ON ai_tasks (external_task_id);
CREATE INDEX IF NOT EXISTS idx_ai_tasks_storyboard ON ai_tasks (storyboard_id);

CREATE TABLE IF NOT EXISTS team_groups (
    id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    name VARCHAR(128) NOT NULL,
    description CLOB,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS group_members (
    group_id BIGINT NOT NULL,
    user_id BIGINT NOT NULL,
    PRIMARY KEY (group_id, user_id)
);

CREATE TABLE IF NOT EXISTS global_assets (
    id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    creator_user_id BIGINT NOT NULL,
    name VARCHAR(256) NOT NULL,
    asset_type VARCHAR(32) NOT NULL,
    library_type VARCHAR(16) NOT NULL DEFAULT 'personal',
    tags VARCHAR(512),
    image_tos_key VARCHAR(512),
    image_url VARCHAR(1024),
    description CLOB,
    is_favorite TINYINT NOT NULL DEFAULT 0,
    source_project_id BIGINT,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE INDEX IF NOT EXISTS idx_global_assets_tenant_type ON global_assets (tenant_id, asset_type, library_type);
CREATE INDEX IF NOT EXISTS idx_global_assets_creator ON global_assets (creator_user_id);

CREATE TABLE IF NOT EXISTS graph_runs (
    id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    project_id BIGINT NOT NULL,
    goal CLOB NOT NULL,
    status VARCHAR(16) NOT NULL DEFAULT 'PENDING',
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE INDEX IF NOT EXISTS idx_graph_runs_project ON graph_runs (project_id);
CREATE INDEX IF NOT EXISTS idx_graph_runs_tenant_project ON graph_runs (tenant_id, project_id);

CREATE TABLE IF NOT EXISTS graph_steps (
    id BIGINT NOT NULL,
    run_id BIGINT NOT NULL,
    step_key VARCHAR(64) NOT NULL,
    step_name VARCHAR(128) NOT NULL,
    agent_type VARCHAR(16) NOT NULL,
    status VARCHAR(16) NOT NULL DEFAULT 'PENDING',
    score CHAR(1),
    score_detail CLOB,
    output CLOB,
    duration_ms BIGINT,
    started_at TIMESTAMP,
    done_at TIMESTAMP,
    seq INT NOT NULL DEFAULT 0,
    PRIMARY KEY (id),
    UNIQUE (run_id, step_key)
);

CREATE INDEX IF NOT EXISTS idx_graph_steps_run ON graph_steps (run_id);

CREATE TABLE IF NOT EXISTS script_understandings (
    id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    project_id BIGINT NOT NULL,
    asset_id BIGINT,
    understanding_json CLOB,
    evidence_hash VARCHAR(64),
    coverage_report_json CLOB,
    quality_status VARCHAR(32) NOT NULL DEFAULT 'PENDING',
    quality_issues_json CLOB,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE INDEX IF NOT EXISTS idx_script_understandings_tenant_project ON script_understandings (tenant_id, project_id);
CREATE INDEX IF NOT EXISTS idx_script_understandings_asset ON script_understandings (asset_id);

CREATE TABLE IF NOT EXISTS project_consistency_bibles (
    id BIGINT NOT NULL,
    tenant_id BIGINT NOT NULL,
    project_id BIGINT NOT NULL,
    bible_json CLOB,
    source_version VARCHAR(64),
    locked_fields_json CLOB,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    UNIQUE (tenant_id, project_id)
);

CREATE TABLE IF NOT EXISTS agent_run_plans (
    id BIGINT NOT NULL,
    run_id BIGINT NOT NULL,
    run_mode VARCHAR(64) NOT NULL,
    reasoning_summary CLOB,
    planned_steps_json CLOB,
    skipped_steps_json CLOB,
    step_inputs_json CLOB,
    quality_rules_json CLOB,
    model_policy_json CLOB,
    context_options_json CLOB,
    idempotency_key VARCHAR(128),
    plan_version VARCHAR(32) NOT NULL DEFAULT 'v1',
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id),
    UNIQUE (run_id)
);

CREATE INDEX IF NOT EXISTS idx_agent_run_plans_idempotency ON agent_run_plans (idempotency_key);

CREATE TABLE IF NOT EXISTS agent_prompt_snapshots (
    id BIGINT NOT NULL,
    run_id BIGINT NOT NULL,
    step_key VARCHAR(64) NOT NULL,
    prompt_role VARCHAR(64) NOT NULL,
    system_prompt_version VARCHAR(64),
    context_hash VARCHAR(64),
    context_summary CLOB,
    request_json CLOB,
    response_raw CLOB,
    parsed_output_json CLOB,
    validation_result_json CLOB,
    model_provider VARCHAR(64),
    model_id VARCHAR(128),
    latency_ms BIGINT,
    error_message CLOB,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (id)
);

CREATE INDEX IF NOT EXISTS idx_agent_prompt_snapshots_run_step ON agent_prompt_snapshots (run_id, step_key);
