CREATE TABLE IF NOT EXISTS scheduled_jobs (
    id UUID PRIMARY KEY,
    user_uuid UUID REFERENCES users(id) ON DELETE CASCADE,
    job_type VARCHAR(100) NOT NULL,
    payload JSONB NOT NULL DEFAULT '{}'::JSONB,
    run_at TIMESTAMPTZ NOT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'pending',
    attempts INTEGER NOT NULL DEFAULT 0,
    max_attempts INTEGER NOT NULL DEFAULT 3,
    leased_by VARCHAR(255),
    lease_until TIMESTAMPTZ,
    last_error TEXT,
    idempotency_key VARCHAR(255),
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    completed_at TIMESTAMPTZ,
    cancelled_at TIMESTAMPTZ,
    CONSTRAINT scheduled_jobs_status_check
        CHECK (status IN ('pending', 'running', 'completed', 'failed', 'cancelled')),
    CONSTRAINT scheduled_jobs_attempts_check
        CHECK (attempts >= 0 AND max_attempts > 0),
    CONSTRAINT scheduled_jobs_idempotency_unique
        UNIQUE (job_type, idempotency_key)
);

CREATE INDEX IF NOT EXISTS scheduled_jobs_claim_idx
    ON scheduled_jobs (run_at, created_at)
    WHERE status = 'pending';

CREATE INDEX IF NOT EXISTS scheduled_jobs_expired_lease_idx
    ON scheduled_jobs (lease_until)
    WHERE status = 'running';

CREATE INDEX IF NOT EXISTS scheduled_jobs_user_idx
    ON scheduled_jobs (user_uuid, created_at DESC);
