-- Schema for jcode telemetry D1 database

CREATE TABLE IF NOT EXISTS events (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    telemetry_id TEXT NOT NULL,
    event TEXT NOT NULL,
    version TEXT NOT NULL,
    os TEXT NOT NULL,
    arch TEXT NOT NULL,
    provider_start TEXT,
    provider_end TEXT,
    model_start TEXT,
    model_end TEXT,
    provider_switches INTEGER DEFAULT 0,
    model_switches INTEGER DEFAULT 0,
    duration_mins INTEGER,
    duration_secs INTEGER,
    turns INTEGER,
    had_user_prompt INTEGER DEFAULT 0,
    had_assistant_response INTEGER DEFAULT 0,
    assistant_responses INTEGER DEFAULT 0,
    first_assistant_response_ms INTEGER,
    first_tool_call_ms INTEGER,
    first_tool_success_ms INTEGER,
    tool_calls INTEGER DEFAULT 0,
    tool_failures INTEGER DEFAULT 0,
    executed_tool_calls INTEGER DEFAULT 0,
    executed_tool_successes INTEGER DEFAULT 0,
    executed_tool_failures INTEGER DEFAULT 0,
    tool_latency_total_ms INTEGER DEFAULT 0,
    tool_latency_max_ms INTEGER DEFAULT 0,
    file_write_calls INTEGER DEFAULT 0,
    tests_run INTEGER DEFAULT 0,
    tests_passed INTEGER DEFAULT 0,
    input_tokens INTEGER DEFAULT 0,
    output_tokens INTEGER DEFAULT 0,
    cache_read_input_tokens INTEGER DEFAULT 0,
    cache_creation_input_tokens INTEGER DEFAULT 0,
    total_tokens INTEGER DEFAULT 0,
    feature_memory_used INTEGER DEFAULT 0,
    feature_swarm_used INTEGER DEFAULT 0,
    feature_web_used INTEGER DEFAULT 0,
    feature_email_used INTEGER DEFAULT 0,
    feature_mcp_used INTEGER DEFAULT 0,
    feature_side_panel_used INTEGER DEFAULT 0,
    feature_goal_used INTEGER DEFAULT 0,
    feature_selfdev_used INTEGER DEFAULT 0,
    feature_background_used INTEGER DEFAULT 0,
    feature_subagent_used INTEGER DEFAULT 0,
    unique_mcp_servers INTEGER DEFAULT 0,
    session_success INTEGER DEFAULT 0,
    abandoned_before_response INTEGER DEFAULT 0,
    session_stop_reason TEXT,
    agent_role TEXT,
    parent_session_id TEXT,
    agent_active_ms_total INTEGER DEFAULT 0,
    agent_model_ms_total INTEGER DEFAULT 0,
    agent_tool_ms_total INTEGER DEFAULT 0,
    session_idle_ms_total INTEGER DEFAULT 0,
    agent_blocked_ms_total INTEGER DEFAULT 0,
    time_to_first_agent_action_ms INTEGER,
    time_to_first_useful_action_ms INTEGER,
    spawned_agent_count INTEGER DEFAULT 0,
    background_task_count INTEGER DEFAULT 0,
    background_task_completed_count INTEGER DEFAULT 0,
    subagent_task_count INTEGER DEFAULT 0,
    subagent_success_count INTEGER DEFAULT 0,
    swarm_task_count INTEGER DEFAULT 0,
    swarm_success_count INTEGER DEFAULT 0,
    user_cancelled_count INTEGER DEFAULT 0,
    transport_https INTEGER DEFAULT 0,
    transport_persistent_ws_fresh INTEGER DEFAULT 0,
    transport_persistent_ws_reuse INTEGER DEFAULT 0,
    transport_cli_subprocess INTEGER DEFAULT 0,
    transport_native_http2 INTEGER DEFAULT 0,
    transport_other INTEGER DEFAULT 0,
    resumed_session INTEGER DEFAULT 0,
    end_reason TEXT,
    auth_provider TEXT,
    auth_method TEXT,
    -- Failure reason label for onboarding_step step='auth_failed' events
    -- (classify_auth_failure_message labels, e.g. callback_timeout,
    -- validation_failed, oauth_rate_limited). Added in migration 0015.
    auth_failure_reason TEXT,
    from_version TEXT,
    event_id TEXT,
    session_id TEXT,
    schema_version INTEGER DEFAULT 1,
    build_channel TEXT,
    is_git_checkout INTEGER DEFAULT 0,
    is_ci INTEGER DEFAULT 0,
    ran_from_cargo INTEGER DEFAULT 0,
    step TEXT,
    milestone_elapsed_ms INTEGER,
    feedback_rating TEXT,
    feedback_reason TEXT,
    feedback_text TEXT,
    -- NOTE: schema-v5 per-turn fields (turn_index, turn timings, turn_success,
    -- turn_abandoned, turn_end_reason) and session cadence fields (hour/weekday,
    -- previous_session_gap_secs, sessions_started_24h/7d, concurrency) live in
    -- turn_details / session_details, NOT here. D1 caps tables at 100 columns
    -- and events sits at 96 in production, so it has no headroom. See
    -- migrations/0013_detail_table_turn_session_fields.sql.
    error_provider_timeout INTEGER DEFAULT 0,
    error_auth_failed INTEGER DEFAULT 0,
    error_tool_error INTEGER DEFAULT 0,
    error_mcp_error INTEGER DEFAULT 0,
    error_rate_limited INTEGER DEFAULT 0,
    -- Token subscription plan fields (migration 0016). These two are the only
    -- subscription columns on events because the table is near D1's
    -- 100-column cap (96 in production before 0016); web-only fields live in
    -- web_details below.
    account_id TEXT,
    tier TEXT,
    created_at TEXT DEFAULT (datetime('now'))
);

CREATE INDEX IF NOT EXISTS idx_events_telemetry_id ON events(telemetry_id);
CREATE INDEX IF NOT EXISTS idx_events_event ON events(event);
CREATE INDEX IF NOT EXISTS idx_events_created_at ON events(created_at);
CREATE INDEX IF NOT EXISTS idx_events_event_created_telemetry ON events(event, created_at, telemetry_id);
CREATE INDEX IF NOT EXISTS idx_events_event_telemetry_created ON events(event, telemetry_id, created_at);
CREATE UNIQUE INDEX IF NOT EXISTS idx_events_event_id ON events(event_id);
CREATE INDEX IF NOT EXISTS idx_events_session_id ON events(session_id);
CREATE INDEX IF NOT EXISTS idx_events_step ON events(step);
CREATE INDEX IF NOT EXISTS idx_events_feedback_rating ON events(feedback_rating);
CREATE INDEX IF NOT EXISTS idx_events_account_id ON events(account_id);
CREATE INDEX IF NOT EXISTS idx_events_event_tier_created ON events(event, tier, created_at);

-- Website beacon detail rows (web_pageview / web_cta_click / web_vital /
-- web_error), keyed by event_id like session_details / turn_details. Added in
-- migration 0016 and extended with privacy-safe quality fields in 0018.
CREATE TABLE IF NOT EXISTS web_details (
    event_id TEXT PRIMARY KEY,
    path TEXT,
    referrer TEXT,
    visitor_id TEXT,
    utm_source TEXT,
    utm_medium TEXT,
    utm_campaign TEXT,
    cta TEXT,
    metric_name TEXT,
    metric_value REAL,
    rating TEXT,
    error_kind TEXT,
    FOREIGN KEY (event_id) REFERENCES events(event_id)
);

CREATE INDEX IF NOT EXISTS idx_web_details_visitor_id ON web_details(visitor_id);
CREATE INDEX IF NOT EXISTS idx_web_details_path ON web_details(path);
CREATE INDEX IF NOT EXISTS idx_web_details_cta ON web_details(cta);

-- Privacy-safe sponsored-discovery attempt details. Free-text query and reason
-- content are never sent by the client and therefore cannot be stored here.
CREATE TABLE IF NOT EXISTS discovery_details (
    event_id TEXT PRIMARY KEY,
    request_id TEXT NOT NULL,
    phase TEXT NOT NULL,
    category TEXT,
    selected_tool TEXT,
    outcome TEXT NOT NULL,
    failure_reason TEXT,
    http_status INTEGER,
    latency_ms INTEGER NOT NULL DEFAULT 0,
    response_bytes INTEGER,
    result_count INTEGER,
    query_present INTEGER NOT NULL DEFAULT 0,
    reason_present INTEGER NOT NULL DEFAULT 0,
    custom_endpoint INTEGER NOT NULL DEFAULT 0,
    FOREIGN KEY (event_id) REFERENCES events(event_id)
);

CREATE UNIQUE INDEX IF NOT EXISTS idx_discovery_request_id ON discovery_details(request_id);
CREATE INDEX IF NOT EXISTS idx_discovery_phase_outcome ON discovery_details(phase, outcome);
CREATE INDEX IF NOT EXISTS idx_discovery_category_outcome ON discovery_details(category, outcome);
CREATE INDEX IF NOT EXISTS idx_discovery_selected_tool ON discovery_details(selected_tool);
CREATE INDEX IF NOT EXISTS idx_discovery_failure_reason ON discovery_details(failure_reason);

CREATE TABLE IF NOT EXISTS session_details (
    event_id TEXT PRIMARY KEY,
    session_start_hour_utc INTEGER,
    session_start_weekday_utc INTEGER,
    session_end_hour_utc INTEGER,
    session_end_weekday_utc INTEGER,
    previous_session_gap_secs INTEGER,
    sessions_started_24h INTEGER DEFAULT 0,
    sessions_started_7d INTEGER DEFAULT 0,
    active_sessions_at_start INTEGER DEFAULT 0,
    other_active_sessions_at_start INTEGER DEFAULT 0,
    max_concurrent_sessions INTEGER DEFAULT 0,
    multi_sessioned INTEGER DEFAULT 0,
    first_file_edit_ms INTEGER,
    first_test_pass_ms INTEGER,
    tool_cat_read_search INTEGER DEFAULT 0,
    tool_cat_write INTEGER DEFAULT 0,
    tool_cat_shell INTEGER DEFAULT 0,
    tool_cat_web INTEGER DEFAULT 0,
    tool_cat_memory INTEGER DEFAULT 0,
    tool_cat_subagent INTEGER DEFAULT 0,
    tool_cat_swarm INTEGER DEFAULT 0,
    tool_cat_email INTEGER DEFAULT 0,
    tool_cat_side_panel INTEGER DEFAULT 0,
    tool_cat_goal INTEGER DEFAULT 0,
    tool_cat_mcp INTEGER DEFAULT 0,
    tool_cat_other INTEGER DEFAULT 0,
    command_login_used INTEGER DEFAULT 0,
    command_model_used INTEGER DEFAULT 0,
    command_usage_used INTEGER DEFAULT 0,
    command_resume_used INTEGER DEFAULT 0,
    command_memory_used INTEGER DEFAULT 0,
    command_swarm_used INTEGER DEFAULT 0,
    command_goal_used INTEGER DEFAULT 0,
    command_selfdev_used INTEGER DEFAULT 0,
    command_feedback_used INTEGER DEFAULT 0,
    command_other_used INTEGER DEFAULT 0,
    workflow_chat_only INTEGER DEFAULT 0,
    workflow_coding_used INTEGER DEFAULT 0,
    workflow_research_used INTEGER DEFAULT 0,
    workflow_tests_used INTEGER DEFAULT 0,
    workflow_background_used INTEGER DEFAULT 0,
    workflow_subagent_used INTEGER DEFAULT 0,
    workflow_swarm_used INTEGER DEFAULT 0,
    project_repo_present INTEGER DEFAULT 0,
    project_lang_rust INTEGER DEFAULT 0,
    project_lang_js_ts INTEGER DEFAULT 0,
    project_lang_python INTEGER DEFAULT 0,
    project_lang_go INTEGER DEFAULT 0,
    project_lang_markdown INTEGER DEFAULT 0,
    project_lang_mixed INTEGER DEFAULT 0,
    days_since_install INTEGER,
    active_days_7d INTEGER DEFAULT 0,
    active_days_30d INTEGER DEFAULT 0,
    FOREIGN KEY (event_id) REFERENCES events(event_id)
);

CREATE TABLE IF NOT EXISTS turn_details (
    event_id TEXT PRIMARY KEY,
    turn_index INTEGER,
    turn_started_ms INTEGER,
    turn_active_duration_ms INTEGER,
    idle_before_turn_ms INTEGER,
    idle_after_turn_ms INTEGER,
    turn_success INTEGER DEFAULT 0,
    turn_abandoned INTEGER DEFAULT 0,
    turn_end_reason TEXT,
    input_tokens INTEGER DEFAULT 0,
    output_tokens INTEGER DEFAULT 0,
    total_tokens INTEGER DEFAULT 0,
    assistant_responses INTEGER DEFAULT 0,
    first_assistant_response_ms INTEGER,
    first_tool_call_ms INTEGER,
    first_tool_success_ms INTEGER,
    first_file_edit_ms INTEGER,
    first_test_pass_ms INTEGER,
    tool_calls INTEGER DEFAULT 0,
    tool_failures INTEGER DEFAULT 0,
    executed_tool_calls INTEGER DEFAULT 0,
    executed_tool_successes INTEGER DEFAULT 0,
    executed_tool_failures INTEGER DEFAULT 0,
    tool_latency_total_ms INTEGER DEFAULT 0,
    tool_latency_max_ms INTEGER DEFAULT 0,
    file_write_calls INTEGER DEFAULT 0,
    tests_run INTEGER DEFAULT 0,
    tests_passed INTEGER DEFAULT 0,
    feature_memory_used INTEGER DEFAULT 0,
    feature_swarm_used INTEGER DEFAULT 0,
    feature_web_used INTEGER DEFAULT 0,
    feature_email_used INTEGER DEFAULT 0,
    feature_mcp_used INTEGER DEFAULT 0,
    feature_side_panel_used INTEGER DEFAULT 0,
    feature_goal_used INTEGER DEFAULT 0,
    feature_selfdev_used INTEGER DEFAULT 0,
    feature_background_used INTEGER DEFAULT 0,
    feature_subagent_used INTEGER DEFAULT 0,
    unique_mcp_servers INTEGER DEFAULT 0,
    tool_cat_read_search INTEGER DEFAULT 0,
    tool_cat_write INTEGER DEFAULT 0,
    tool_cat_shell INTEGER DEFAULT 0,
    tool_cat_web INTEGER DEFAULT 0,
    tool_cat_memory INTEGER DEFAULT 0,
    tool_cat_subagent INTEGER DEFAULT 0,
    tool_cat_swarm INTEGER DEFAULT 0,
    tool_cat_email INTEGER DEFAULT 0,
    tool_cat_side_panel INTEGER DEFAULT 0,
    tool_cat_goal INTEGER DEFAULT 0,
    tool_cat_mcp INTEGER DEFAULT 0,
    tool_cat_other INTEGER DEFAULT 0,
    workflow_chat_only INTEGER DEFAULT 0,
    workflow_coding_used INTEGER DEFAULT 0,
    workflow_research_used INTEGER DEFAULT 0,
    workflow_tests_used INTEGER DEFAULT 0,
    workflow_background_used INTEGER DEFAULT 0,
    workflow_subagent_used INTEGER DEFAULT 0,
    workflow_swarm_used INTEGER DEFAULT 0,
    FOREIGN KEY (event_id) REFERENCES events(event_id)
);

CREATE TABLE IF NOT EXISTS daily_active_users (
    activity_date TEXT NOT NULL,
    telemetry_id TEXT NOT NULL,
    first_seen_at TEXT DEFAULT (datetime('now')),
    last_seen_at TEXT DEFAULT (datetime('now')),
    raw_active INTEGER DEFAULT 0,
    meaningful_active INTEGER DEFAULT 0,
    release_active INTEGER DEFAULT 0,
    meaningful_release_active INTEGER DEFAULT 0,
    session_start_count INTEGER DEFAULT 0,
    turn_end_count INTEGER DEFAULT 0,
    session_end_count INTEGER DEFAULT 0,
    session_crash_count INTEGER DEFAULT 0,
    ci_active INTEGER DEFAULT 0,
    last_is_ci INTEGER DEFAULT 0,
    last_build_channel TEXT,
    PRIMARY KEY (activity_date, telemetry_id)
);

CREATE INDEX IF NOT EXISTS idx_daily_active_date
    ON daily_active_users(activity_date);

CREATE INDEX IF NOT EXISTS idx_daily_active_date_release
    ON daily_active_users(activity_date, release_active, meaningful_release_active);

CREATE INDEX IF NOT EXISTS idx_daily_active_date_ci
    ON daily_active_users(activity_date, last_is_ci, meaningful_release_active);
