-- +goose Up
-- +goose StatementBegin
CREATE TABLE IF NOT EXISTS repos (
    id              TEXT PRIMARY KEY,
    name            TEXT NOT NULL,
    remote_url      TEXT NOT NULL,
    default_branch  TEXT NOT NULL,
    workspace_root  TEXT NOT NULL,
    credential_ref  TEXT,
    created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS workspace_leases (
    id          TEXT PRIMARY KEY,
    repo_id     TEXT NOT NULL REFERENCES repos(id),
    slot        TEXT NOT NULL,
    path        TEXT NOT NULL,
    state       TEXT NOT NULL,
    expires_at  TIMESTAMPTZ,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at  TIMESTAMPTZ NOT NULL DEFAULT now(),
    UNIQUE (repo_id, slot)
);

CREATE TABLE IF NOT EXISTS operations (
    id               TEXT PRIMARY KEY,
    repo_id          TEXT NOT NULL REFERENCES repos(id),
    type             TEXT NOT NULL CHECK (type IN ('clone', 'fetch', 'commit', 'push', 'agent_run')),
    state            TEXT NOT NULL CHECK (state IN ('queued', 'running', 'succeeded', 'failed', 'cancelled')),
    idempotency_key  TEXT CHECK (idempotency_key IS NULL OR btrim(idempotency_key) <> ''),
    created_by       TEXT NOT NULL CHECK (btrim(created_by) <> ''),
    created_at       TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at       TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE UNIQUE INDEX IF NOT EXISTS ux_operations_idempotency
    ON operations (idempotency_key)
    WHERE idempotency_key IS NOT NULL;

CREATE TABLE IF NOT EXISTS operation_events (
    id            TEXT PRIMARY KEY,
    operation_id  TEXT REFERENCES operations(id),
    type          TEXT NOT NULL,
    subject       TEXT NOT NULL,
    payload       JSONB NOT NULL DEFAULT '{}'::jsonb,
    created_at    TIMESTAMPTZ NOT NULL DEFAULT now(),
    published_at  TIMESTAMPTZ
);

CREATE INDEX IF NOT EXISTS ix_operation_events_operation_ordering
    ON operation_events (operation_id, created_at, id);

CREATE INDEX IF NOT EXISTS ix_operation_events_pending_ordering
    ON operation_events (created_at, id)
    WHERE published_at IS NULL;

CREATE TABLE IF NOT EXISTS revision_cursors (
    repo_id      TEXT NOT NULL,
    branch       TEXT NOT NULL,
    revision     TEXT NOT NULL,
    observed_at  TIMESTAMPTZ NOT NULL DEFAULT now(),
    PRIMARY KEY (repo_id, branch)
);

ALTER TABLE revision_cursors DROP CONSTRAINT IF EXISTS revision_cursors_repo_id_fkey;

CREATE TABLE IF NOT EXISTS branch_watches (
    id          TEXT PRIMARY KEY,
    provider    TEXT NOT NULL,
    repo_id     TEXT NOT NULL,
    branch      TEXT NOT NULL,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT now(),
    UNIQUE (provider, repo_id, branch)
);

CREATE TABLE IF NOT EXISTS provider_deliveries (
    id           TEXT PRIMARY KEY,
    provider     TEXT NOT NULL,
    delivery_id  TEXT NOT NULL,
    dedupe_key   TEXT NOT NULL,
    event_id     TEXT NOT NULL,
    repo_id      TEXT NOT NULL,
    branch       TEXT NOT NULL,
    revision     TEXT NOT NULL,
    created_at   TIMESTAMPTZ NOT NULL DEFAULT now(),
    UNIQUE (provider, dedupe_key)
);
-- +goose StatementEnd

-- +goose Down
-- +goose StatementBegin
DROP TABLE IF EXISTS provider_deliveries;
DROP TABLE IF EXISTS branch_watches;
DROP TABLE IF EXISTS revision_cursors;
DROP TABLE IF EXISTS operation_events;
DROP TABLE IF EXISTS operations;
DROP TABLE IF EXISTS workspace_leases;
DROP TABLE IF EXISTS repos;
-- +goose StatementEnd
