CREATE TABLE IF NOT EXISTS batch_workflows (
    id BIGSERIAL PRIMARY KEY,
    run_id TEXT NOT NULL UNIQUE,
    root_run_id TEXT NOT NULL,
    workflow JSONB NOT NULL,
    status TEXT NOT NULL,
    parent_run_id TEXT,
    fork_name TEXT,
    error_sexpr TEXT,
    next_event_ordinal BIGINT NOT NULL DEFAULT 0 CHECK (next_event_ordinal >= 0),
    causal_cursor JSONB NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    quiescent BOOLEAN NOT NULL DEFAULT FALSE,
    quiesced_at TIMESTAMPTZ
);

CREATE INDEX IF NOT EXISTS batch_workflows_status_idx
    ON batch_workflows (status, quiescent, updated_at);

CREATE INDEX IF NOT EXISTS batch_workflows_parent_idx
    ON batch_workflows (parent_run_id);

CREATE TABLE IF NOT EXISTS batch_continuations (
    id BIGSERIAL PRIMARY KEY,
    continuation_id TEXT NOT NULL UNIQUE,
    workflow_run_id TEXT NOT NULL,
    kind TEXT NOT NULL,
    status TEXT NOT NULL,
    provider TEXT,
    provider_batch_id TEXT,
    provider_message_id TEXT,
    output_key TEXT,
    request JSONB,
    response JSONB,
    result_type TEXT,
    error_sexpr TEXT,
    usage JSONB,
    input_tokens BIGINT,
    output_tokens BIGINT,
    cache_creation_input_tokens BIGINT,
    cache_read_input_tokens BIGINT,
    server_tool_use JSONB,
    attempt_of TEXT,
    attempt INTEGER NOT NULL DEFAULT 1,
    causal_cursor JSONB NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    submitted_at TIMESTAMPTZ,
    completed_at TIMESTAMPTZ,
    quiescent BOOLEAN NOT NULL DEFAULT FALSE,
    quiesced_at TIMESTAMPTZ
);

CREATE INDEX IF NOT EXISTS batch_continuations_workflow_idx
    ON batch_continuations (workflow_run_id);

CREATE INDEX IF NOT EXISTS batch_continuations_provider_idx
    ON batch_continuations (provider, status, created_at);

CREATE INDEX IF NOT EXISTS batch_continuations_provider_batch_idx
    ON batch_continuations (provider_batch_id);

CREATE TABLE IF NOT EXISTS batch_workflow_events (
    event_id UUID PRIMARY KEY,
    root_run_id TEXT NOT NULL,
    run_id TEXT NOT NULL,
    parent_run_id TEXT,
    fork_name TEXT,
    event_ordinal BIGINT NOT NULL CHECK (event_ordinal >= 0),
    caused_by JSONB NOT NULL,
    event_type TEXT NOT NULL,
    event_version SMALLINT NOT NULL CHECK (event_version > 0),
    continuation_id TEXT,
    event JSONB NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    UNIQUE (run_id, event_ordinal)
);

CREATE INDEX IF NOT EXISTS batch_workflow_events_root_idx
    ON batch_workflow_events (root_run_id, created_at, event_id);

CREATE INDEX IF NOT EXISTS batch_workflow_events_type_idx
    ON batch_workflow_events (event_type, created_at);

CREATE INDEX IF NOT EXISTS batch_workflow_events_continuation_idx
    ON batch_workflow_events (continuation_id)
    WHERE continuation_id IS NOT NULL;

CREATE TABLE IF NOT EXISTS batch_provider_batches (
    id BIGSERIAL PRIMARY KEY,
    provider TEXT NOT NULL,
    provider_batch_id TEXT NOT NULL UNIQUE,
    status TEXT NOT NULL,
    request_count INTEGER NOT NULL,
    response JSONB,
    error_sexpr TEXT,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    submitted_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    completed_at TIMESTAMPTZ,
    quiescent BOOLEAN NOT NULL DEFAULT FALSE,
    quiesced_at TIMESTAMPTZ
);

CREATE INDEX IF NOT EXISTS batch_provider_batches_provider_idx
    ON batch_provider_batches (provider, status, quiescent, submitted_at);

CREATE TABLE IF NOT EXISTS batch_fork_joins (
    id BIGSERIAL PRIMARY KEY,
    parent_run_id TEXT NOT NULL UNIQUE,
    lhs_run_id TEXT NOT NULL,
    rhs_run_id TEXT NOT NULL,
    status TEXT NOT NULL,
    error_sexpr TEXT,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    quiescent BOOLEAN NOT NULL DEFAULT FALSE,
    quiesced_at TIMESTAMPTZ
);

CREATE INDEX IF NOT EXISTS batch_fork_joins_status_idx
    ON batch_fork_joins (status, quiescent, updated_at);
