package storage

import (
	"context"
	"crypto/rand"
	"database/sql"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/jackc/pgx/v5"
	"github.com/jackc/pgx/v5/pgconn"
	"github.com/jackc/pgx/v5/pgxpool"

	"git.toki-labs.com/toki/gito/services/core/internal/core"
	"git.toki-labs.com/toki/gito/services/core/internal/provider"
)

// PgStore is a pgxpool-backed Store implementation.
type PgStore struct {
	pool              *pgxpool.Pool
	repos             *pgRepoStore
	leases            *pgWorkspaceLeaseStore
	ops               *pgOperationStore
	opEvents          *pgOperationEventStore
	watches           *pgBranchWatchStore
	cursors           *pgRevisionCursorStore
	deliveries        *pgProviderDeliveryStore
	agentRunInputs    *pgAgentRunInputStore
	webhookDeliveries *pgWebhookDeliveryStore
	providerConfigs   *pgProviderConfigStore
}

// NewPgStore opens a pgxpool connection and optionally applies a migration.
// migrationSQL is the raw SQL content (e.g. from //go:embed); pass an empty
// string to skip migration.
func NewPgStore(ctx context.Context, dsn string, migrationSQL string) (*PgStore, error) {
	pool, err := pgxpool.New(ctx, dsn)
	if err != nil {
		return nil, fmt.Errorf("pgstore: open pool: %w", err)
	}
	if err := pool.Ping(ctx); err != nil {
		pool.Close()
		return nil, fmt.Errorf("pgstore: ping: %w", err)
	}
	if migrationSQL != "" {
		if err := applyMigrationSQL(ctx, pool, migrationSQL); err != nil {
			pool.Close()
			return nil, fmt.Errorf("pgstore: migration: %w", err)
		}
	}
	s := &PgStore{pool: pool}
	s.repos = &pgRepoStore{pool: pool}
	s.leases = &pgWorkspaceLeaseStore{pool: pool}
	s.ops = &pgOperationStore{pool: pool}
	s.opEvents = &pgOperationEventStore{pool: pool}
	s.watches = &pgBranchWatchStore{pool: pool}
	s.cursors = &pgRevisionCursorStore{pool: pool}
	s.deliveries = &pgProviderDeliveryStore{pool: pool}
	s.agentRunInputs = &pgAgentRunInputStore{pool: pool}
	s.webhookDeliveries = &pgWebhookDeliveryStore{pool: pool}
	s.providerConfigs = newPgProviderConfigStore(pool)
	return s, nil
}

func (s *PgStore) Close() { s.pool.Close() }

func (s *PgStore) Ping(ctx context.Context) error { return s.pool.Ping(ctx) }

func (s *PgStore) Repos() RepoStore                          { return s.repos }
func (s *PgStore) WorkspaceLeases() WorkspaceLeaseStore      { return s.leases }
func (s *PgStore) Operations() OperationStore                { return s.ops }
func (s *PgStore) OperationEvents() OperationEventStore      { return s.opEvents }
func (s *PgStore) BranchWatches() BranchWatchStore           { return s.watches }
func (s *PgStore) RevisionCursors() RevisionCursorStore      { return s.cursors }
func (s *PgStore) ProviderDeliveries() ProviderDeliveryStore { return s.deliveries }
func (s *PgStore) AgentRunInputs() AgentRunInputStore        { return s.agentRunInputs }
func (s *PgStore) WebhookDeliveries() WebhookDeliveryStore   { return s.webhookDeliveries }
func (s *PgStore) ProviderConfigs() ProviderConfigStore      { return s.providerConfigs }

// applyMigrationSQL executes the Up block extracted from goose-style SQL content.
func applyMigrationSQL(ctx context.Context, pool *pgxpool.Pool, content string) error {
	sql := extractUpBlock(content)
	if sql == "" {
		return nil
	}
	_, err := pool.Exec(ctx, sql)
	return err
}

func extractUpBlock(content string) string {
	const beginMarker = "-- +goose StatementBegin"
	const endMarker = "-- +goose StatementEnd"
	const upMarker = "-- +goose Up"

	upIdx := strings.Index(content, upMarker)
	if upIdx < 0 {
		return ""
	}
	after := content[upIdx:]
	beginIdx := strings.Index(after, beginMarker)
	endIdx := strings.Index(after, endMarker)
	if beginIdx < 0 || endIdx < 0 || endIdx <= beginIdx {
		return ""
	}
	return strings.TrimSpace(after[beginIdx+len(beginMarker) : endIdx])
}

// pgRepoStore

type pgRepoStore struct{ pool *pgxpool.Pool }

func (s *pgRepoStore) CreateRepo(ctx context.Context, repo core.Repo) error {
	repo, err := normalizeRepo(repo)
	if err != nil {
		return err
	}

	const q = `
		INSERT INTO repos (id, name, remote_url, default_branch, workspace_root, credential_ref)
		VALUES ($1, $2, $3, $4, $5, $6)
	`
	_, err = s.pool.Exec(ctx, q,
		repo.ID,
		repo.Name,
		repo.RemoteURL,
		repo.DefaultBranch,
		repo.WorkspaceRoot,
		nullableString(repo.CredentialRef),
	)
	if err != nil {
		if isUniqueViolation(err) {
			return fmt.Errorf("%w: %s", ErrRepoAlreadyExists, repo.ID)
		}
		return fmt.Errorf("create repo: %w", err)
	}
	return nil
}

func (s *pgRepoStore) GetRepo(ctx context.Context, id string) (core.Repo, error) {
	id = strings.TrimSpace(id)
	if id == "" {
		return core.Repo{}, fmt.Errorf("%w: id is required", ErrInvalidRepo)
	}

	const q = `
		SELECT id, name, remote_url, default_branch, workspace_root, credential_ref
		FROM repos
		WHERE id=$1
	`
	repo, err := scanRepo(s.pool.QueryRow(ctx, q, id))
	if err != nil {
		if isNoRows(err) {
			return core.Repo{}, fmt.Errorf("%w: %s", ErrRepoNotFound, id)
		}
		return core.Repo{}, fmt.Errorf("get repo: %w", err)
	}
	return repo, nil
}

func (s *pgRepoStore) ListRepos(ctx context.Context) ([]core.Repo, error) {
	const q = `
		SELECT id, name, remote_url, default_branch, workspace_root, credential_ref
		FROM repos
		ORDER BY id
	`
	rows, err := s.pool.Query(ctx, q)
	if err != nil {
		return nil, fmt.Errorf("list repos: %w", err)
	}
	defer rows.Close()

	var out []core.Repo
	for rows.Next() {
		repo, err := scanRepo(rows)
		if err != nil {
			return nil, fmt.Errorf("scan repo: %w", err)
		}
		out = append(out, repo)
	}
	return out, rows.Err()
}

func (s *pgRepoStore) UpdateRepo(ctx context.Context, repo core.Repo) error {
	repo, err := normalizeRepo(repo)
	if err != nil {
		return err
	}

	const q = `
		UPDATE repos
		SET name=$2,
			remote_url=$3,
			default_branch=$4,
			workspace_root=$5,
			credential_ref=$6,
			updated_at=now()
		WHERE id=$1
	`
	tag, err := s.pool.Exec(ctx, q,
		repo.ID,
		repo.Name,
		repo.RemoteURL,
		repo.DefaultBranch,
		repo.WorkspaceRoot,
		nullableString(repo.CredentialRef),
	)
	if err != nil {
		return fmt.Errorf("update repo: %w", err)
	}
	if tag.RowsAffected() == 0 {
		return fmt.Errorf("%w: %s", ErrRepoNotFound, repo.ID)
	}
	return nil
}

func normalizeRepo(repo core.Repo) (core.Repo, error) {
	repo.ID = strings.TrimSpace(repo.ID)
	repo.Name = strings.TrimSpace(repo.Name)
	repo.RemoteURL = strings.TrimSpace(repo.RemoteURL)
	repo.DefaultBranch = strings.TrimSpace(repo.DefaultBranch)
	repo.WorkspaceRoot = strings.TrimSpace(repo.WorkspaceRoot)
	repo.CredentialRef = strings.TrimSpace(repo.CredentialRef)

	var missing []string
	if repo.ID == "" {
		missing = append(missing, "id")
	}
	if repo.Name == "" {
		missing = append(missing, "name")
	}
	if repo.RemoteURL == "" {
		missing = append(missing, "remote_url")
	}
	if repo.DefaultBranch == "" {
		missing = append(missing, "default_branch")
	}
	if repo.WorkspaceRoot == "" {
		missing = append(missing, "workspace_root")
	}
	if len(missing) > 0 {
		return core.Repo{}, fmt.Errorf("%w: required fields missing: %s", ErrInvalidRepo, strings.Join(missing, ", "))
	}
	return repo, nil
}

type repoScanner interface {
	Scan(dest ...any) error
}

func scanRepo(scanner repoScanner) (core.Repo, error) {
	var repo core.Repo
	var credentialRef sql.NullString
	if err := scanner.Scan(
		&repo.ID,
		&repo.Name,
		&repo.RemoteURL,
		&repo.DefaultBranch,
		&repo.WorkspaceRoot,
		&credentialRef,
	); err != nil {
		return core.Repo{}, err
	}
	if credentialRef.Valid {
		repo.CredentialRef = credentialRef.String
	}
	return repo, nil
}

func nullableString(value string) any {
	if value == "" {
		return nil
	}
	return value
}

// pgWorkspaceLeaseStore

type pgWorkspaceLeaseStore struct{ pool *pgxpool.Pool }

func (s *pgWorkspaceLeaseStore) SaveLease(ctx context.Context, lease core.WorkspaceLease) error {
	lease, err := normalizeLease(lease)
	if err != nil {
		return err
	}

	const q = `
		INSERT INTO workspace_leases (id, repo_id, slot, path, state, expires_at)
		VALUES ($1, $2, $3, $4, $5, $6)
	`
	_, err = s.pool.Exec(ctx, q,
		lease.ID,
		lease.RepoID,
		lease.Slot,
		lease.Path,
		lease.State,
		nullableTime(lease.ExpiresAt),
	)
	if err != nil {
		if isUniqueViolation(err) {
			return fmt.Errorf("%w: %s", ErrLeaseAlreadyExists, lease.ID)
		}
		return fmt.Errorf("save lease: %w", err)
	}
	return nil
}

func (s *pgWorkspaceLeaseStore) GetLease(ctx context.Context, id string) (core.WorkspaceLease, error) {
	id = strings.TrimSpace(id)
	if id == "" {
		return core.WorkspaceLease{}, fmt.Errorf("%w: id is required", ErrInvalidLease)
	}

	const q = `
		SELECT id, repo_id, slot, path, state, expires_at
		FROM workspace_leases
		WHERE id=$1
	`
	lease, err := scanLease(s.pool.QueryRow(ctx, q, id))
	if err != nil {
		if isNoRows(err) {
			return core.WorkspaceLease{}, fmt.Errorf("%w: %s", ErrLeaseNotFound, id)
		}
		return core.WorkspaceLease{}, fmt.Errorf("get lease: %w", err)
	}
	return lease, nil
}

func (s *pgWorkspaceLeaseStore) ListLeases(ctx context.Context, repoID string) ([]core.WorkspaceLease, error) {
	repoID = strings.TrimSpace(repoID)
	if repoID == "" {
		return nil, fmt.Errorf("%w: repo_id is required", ErrInvalidLease)
	}

	const q = `
		SELECT id, repo_id, slot, path, state, expires_at
		FROM workspace_leases
		WHERE repo_id=$1
		ORDER BY slot
	`
	rows, err := s.pool.Query(ctx, q, repoID)
	if err != nil {
		return nil, fmt.Errorf("list leases: %w", err)
	}
	defer rows.Close()

	var out []core.WorkspaceLease
	for rows.Next() {
		lease, err := scanLease(rows)
		if err != nil {
			return nil, fmt.Errorf("scan lease: %w", err)
		}
		out = append(out, lease)
	}
	return out, rows.Err()
}

func (s *pgWorkspaceLeaseStore) AcquireAvailableLease(ctx context.Context, repoID string, now time.Time, ttl time.Duration) (core.WorkspaceLease, bool, error) {
	repoID = strings.TrimSpace(repoID)
	if repoID == "" {
		return core.WorkspaceLease{}, false, fmt.Errorf("%w: repo_id is required", ErrInvalidLease)
	}
	if ttl <= 0 {
		return core.WorkspaceLease{}, false, fmt.Errorf("%w: ttl must be positive", ErrInvalidLease)
	}

	tx, err := s.pool.Begin(ctx)
	if err != nil {
		return core.WorkspaceLease{}, false, fmt.Errorf("begin lease acquire: %w", err)
	}
	defer tx.Rollback(ctx)

	expiresAt := now.UTC().Add(ttl)
	const q = `
		WITH candidate AS (
			SELECT id
			FROM workspace_leases
			WHERE repo_id=$1 AND state=$2
			ORDER BY slot
			FOR UPDATE SKIP LOCKED
			LIMIT 1
		)
		UPDATE workspace_leases AS lease
		SET state=$3,
			expires_at=$4,
			updated_at=now()
		FROM candidate
		WHERE lease.id=candidate.id
		RETURNING lease.id, lease.repo_id, lease.slot, lease.path, lease.state, lease.expires_at
	`
	lease, err := scanLease(tx.QueryRow(ctx, q, repoID, core.WorkspaceAvailable, core.WorkspaceLeased, expiresAt))
	if err != nil {
		if isNoRows(err) {
			return core.WorkspaceLease{}, false, nil
		}
		return core.WorkspaceLease{}, false, fmt.Errorf("acquire lease: %w", err)
	}
	if err := tx.Commit(ctx); err != nil {
		return core.WorkspaceLease{}, false, fmt.Errorf("commit lease acquire: %w", err)
	}
	return lease, true, nil
}

func (s *pgWorkspaceLeaseStore) ReleaseLease(ctx context.Context, id string, release LeaseRelease) (core.WorkspaceLease, error) {
	id = strings.TrimSpace(id)
	if id == "" {
		return core.WorkspaceLease{}, fmt.Errorf("%w: id is required", ErrInvalidLease)
	}
	nextState, err := leaseStateForRelease(release)
	if err != nil {
		return core.WorkspaceLease{}, err
	}

	const q = `
		UPDATE workspace_leases
		SET state=$2,
			expires_at=NULL,
			updated_at=now()
		WHERE id=$1 AND state=$3
		RETURNING id, repo_id, slot, path, state, expires_at
	`
	lease, err := scanLease(s.pool.QueryRow(ctx, q, id, nextState, core.WorkspaceLeased))
	if err != nil {
		if isNoRows(err) {
			existing, getErr := s.GetLease(ctx, id)
			if getErr != nil {
				return core.WorkspaceLease{}, getErr
			}
			return core.WorkspaceLease{}, fmt.Errorf("%w: lease %s is %s, not %s", ErrInvalidLease, existing.ID, existing.State, core.WorkspaceLeased)
		}
		return core.WorkspaceLease{}, fmt.Errorf("release lease: %w", err)
	}
	return lease, nil
}

func normalizeLease(lease core.WorkspaceLease) (core.WorkspaceLease, error) {
	lease.ID = strings.TrimSpace(lease.ID)
	lease.RepoID = strings.TrimSpace(lease.RepoID)
	lease.Slot = strings.TrimSpace(lease.Slot)
	lease.Path = strings.TrimSpace(lease.Path)

	var missing []string
	if lease.ID == "" {
		missing = append(missing, "id")
	}
	if lease.RepoID == "" {
		missing = append(missing, "repo_id")
	}
	if lease.Slot == "" {
		missing = append(missing, "slot")
	}
	if lease.Path == "" {
		missing = append(missing, "path")
	}
	if len(missing) > 0 {
		return core.WorkspaceLease{}, fmt.Errorf("%w: required fields missing: %s", ErrInvalidLease, strings.Join(missing, ", "))
	}
	if !isValidWorkspaceState(lease.State) {
		return core.WorkspaceLease{}, fmt.Errorf("%w: unsupported state %q", ErrInvalidLease, lease.State)
	}
	return lease, nil
}

func isValidWorkspaceState(state core.WorkspaceState) bool {
	switch state {
	case core.WorkspaceAvailable, core.WorkspaceLeased, core.WorkspaceDirty, core.WorkspaceError:
		return true
	default:
		return false
	}
}

func leaseStateForRelease(release LeaseRelease) (core.WorkspaceState, error) {
	if release.Dirty {
		return core.WorkspaceDirty, nil
	}
	switch release.OperationState {
	case core.OperationSucceeded, core.OperationCancelled:
		return core.WorkspaceAvailable, nil
	case core.OperationFailed:
		return core.WorkspaceError, nil
	default:
		return "", fmt.Errorf("%w: unsupported release operation state %q", ErrInvalidLease, release.OperationState)
	}
}

func scanLease(scanner repoScanner) (core.WorkspaceLease, error) {
	var lease core.WorkspaceLease
	var expiresAt sql.NullTime
	if err := scanner.Scan(
		&lease.ID,
		&lease.RepoID,
		&lease.Slot,
		&lease.Path,
		&lease.State,
		&expiresAt,
	); err != nil {
		return core.WorkspaceLease{}, err
	}
	if expiresAt.Valid {
		value := expiresAt.Time
		lease.ExpiresAt = &value
	}
	return lease, nil
}

func nullableTime(value *time.Time) any {
	if value == nil {
		return nil
	}
	return value.UTC()
}

// pgOperationStore

type pgOperationStore struct{ pool *pgxpool.Pool }

const opColumns = "id, repo_id, type, state, idempotency_key, created_by, created_at, updated_at"
const opReturningColumns = "op.id, op.repo_id, op.type, op.state, op.idempotency_key, op.created_by, op.created_at, op.updated_at"

// opIdempotencyConstraint is the partial unique index on operations.idempotency_key
// (see migrations/00001_initial.sql). A unique violation naming this constraint is
// an idempotent retry; any other unique violation is a duplicate create.
const opIdempotencyConstraint = "ux_operations_idempotency"

func (s *pgOperationStore) CreateOperation(ctx context.Context, op core.Operation) (OperationCreateResult, error) {
	op, err := normalizeOperation(op)
	if err != nil {
		return OperationCreateResult{}, err
	}

	const q = `
		INSERT INTO operations (id, repo_id, type, state, idempotency_key, created_by)
		VALUES ($1, $2, $3, $4, $5, $6)
		RETURNING ` + opColumns
	created, err := scanOperation(s.pool.QueryRow(ctx, q,
		op.ID,
		op.RepoID,
		op.Type,
		op.State,
		nullableString(op.IdempotencyKey),
		op.CreatedBy,
	))
	if err != nil {
		if constraint, ok := uniqueViolationConstraint(err); ok {
			// Only the idempotency index conflict represents an idempotent retry
			// and returns the existing operation. Any other unique violation
			// (id primary key, etc.) is a genuine duplicate create, regardless of
			// whether an idempotency key was supplied.
			if constraint == opIdempotencyConstraint && op.IdempotencyKey != "" {
				existing, getErr := s.getByIdempotencyKey(ctx, op.IdempotencyKey)
				if getErr != nil {
					return OperationCreateResult{}, getErr
				}
				return OperationCreateResult{Operation: existing, Created: false}, nil
			}
			return OperationCreateResult{}, fmt.Errorf("%w: %s", ErrOperationAlreadyExists, op.ID)
		}
		return OperationCreateResult{}, fmt.Errorf("create operation: %w", err)
	}
	return OperationCreateResult{Operation: created, Created: true}, nil
}

func (s *pgOperationStore) getByIdempotencyKey(ctx context.Context, key string) (core.Operation, error) {
	const q = `SELECT ` + opColumns + ` FROM operations WHERE idempotency_key=$1`
	op, err := scanOperation(s.pool.QueryRow(ctx, q, key))
	if err != nil {
		if isNoRows(err) {
			return core.Operation{}, fmt.Errorf("%w: idempotency_key %s", ErrOperationNotFound, key)
		}
		return core.Operation{}, fmt.Errorf("get operation by idempotency key: %w", err)
	}
	return op, nil
}

func (s *pgOperationStore) GetOperation(ctx context.Context, id string) (core.Operation, error) {
	id = strings.TrimSpace(id)
	if id == "" {
		return core.Operation{}, fmt.Errorf("%w: id is required", ErrInvalidOperation)
	}

	const q = `SELECT ` + opColumns + ` FROM operations WHERE id=$1`
	op, err := scanOperation(s.pool.QueryRow(ctx, q, id))
	if err != nil {
		if isNoRows(err) {
			return core.Operation{}, fmt.Errorf("%w: %s", ErrOperationNotFound, id)
		}
		return core.Operation{}, fmt.Errorf("get operation: %w", err)
	}
	return op, nil
}

func (s *pgOperationStore) ListOperations(ctx context.Context, repoID string) ([]core.Operation, error) {
	repoID = strings.TrimSpace(repoID)
	if repoID == "" {
		return nil, fmt.Errorf("%w: repo_id is required", ErrInvalidOperation)
	}

	const q = `SELECT ` + opColumns + ` FROM operations WHERE repo_id=$1 ORDER BY created_at, id`
	rows, err := s.pool.Query(ctx, q, repoID)
	if err != nil {
		return nil, fmt.Errorf("list operations: %w", err)
	}
	defer rows.Close()

	var out []core.Operation
	for rows.Next() {
		op, err := scanOperation(rows)
		if err != nil {
			return nil, fmt.Errorf("scan operation: %w", err)
		}
		out = append(out, op)
	}
	return out, rows.Err()
}

func (s *pgOperationStore) StartOperation(ctx context.Context, id string, now time.Time) (core.Operation, error) {
	return s.transition(ctx, id, core.OperationRunning, now)
}

func (s *pgOperationStore) SucceedOperation(ctx context.Context, id string, now time.Time) (core.Operation, error) {
	return s.transition(ctx, id, core.OperationSucceeded, now)
}

func (s *pgOperationStore) FailOperation(ctx context.Context, id string, now time.Time) (core.Operation, error) {
	return s.transition(ctx, id, core.OperationFailed, now)
}

func (s *pgOperationStore) CancelOperation(ctx context.Context, id string, now time.Time) (core.Operation, error) {
	return s.transition(ctx, id, core.OperationCancelled, now)
}

func (s *pgOperationStore) PickQueuedOperation(ctx context.Context, now time.Time) (core.Operation, bool, error) {
	const q = `
		WITH candidate AS (
			SELECT id
			FROM operations
			WHERE state=$1
			ORDER BY created_at, id
			FOR UPDATE SKIP LOCKED
			LIMIT 1
		)
		UPDATE operations AS op
		SET state=$2, updated_at=$3
		FROM candidate
		WHERE op.id=candidate.id
		RETURNING ` + opReturningColumns

	op, err := scanOperation(s.pool.QueryRow(ctx, q, core.OperationQueued, core.OperationRunning, now.UTC()))
	if err != nil {
		if isNoRows(err) {
			return core.Operation{}, false, nil
		}
		return core.Operation{}, false, fmt.Errorf("pick queued operation: %w", err)
	}
	return op, true, nil
}

func (s *pgOperationStore) PickQueuedAgentRunOperation(ctx context.Context, now time.Time) (core.Operation, bool, error) {
	const q = `
		WITH candidate AS (
			SELECT id
			FROM operations
			WHERE state=$1 AND type=$2
			ORDER BY created_at, id
			FOR UPDATE SKIP LOCKED
			LIMIT 1
		)
		UPDATE operations AS op
		SET state=$3, updated_at=$4
		FROM candidate
		WHERE op.id=candidate.id
		RETURNING ` + opReturningColumns

	op, err := scanOperation(s.pool.QueryRow(ctx, q, core.OperationQueued, core.OperationAgentRun, core.OperationRunning, now.UTC()))
	if err != nil {
		if isNoRows(err) {
			return core.Operation{}, false, nil
		}
		return core.Operation{}, false, fmt.Errorf("pick queued agent_run operation: %w", err)
	}
	return op, true, nil
}

// transition reads the current operation, validates the state change against
// the core transition rules, and persists the next state with an optimistic
// guard on the observed current state.
func (s *pgOperationStore) transition(ctx context.Context, id string, next core.OperationState, now time.Time) (core.Operation, error) {
	id = strings.TrimSpace(id)
	if id == "" {
		return core.Operation{}, fmt.Errorf("%w: id is required", ErrInvalidOperation)
	}

	current, err := s.GetOperation(ctx, id)
	if err != nil {
		return core.Operation{}, err
	}
	if !current.State.CanTransitionTo(next) {
		return core.Operation{}, fmt.Errorf("%w: cannot transition %s from %s to %s", ErrInvalidOperation, id, current.State, next)
	}

	const q = `
		UPDATE operations
		SET state=$3,
			updated_at=$4
		WHERE id=$1 AND state=$2
		RETURNING ` + opColumns
	op, err := scanOperation(s.pool.QueryRow(ctx, q, id, current.State, next, now.UTC()))
	if err != nil {
		if isNoRows(err) {
			// State changed between read and update; surface as an invalid transition.
			return core.Operation{}, fmt.Errorf("%w: %s no longer in state %s", ErrInvalidOperation, id, current.State)
		}
		return core.Operation{}, fmt.Errorf("transition operation: %w", err)
	}
	return op, nil
}

func normalizeOperation(op core.Operation) (core.Operation, error) {
	op.ID = strings.TrimSpace(op.ID)
	op.RepoID = strings.TrimSpace(op.RepoID)
	op.IdempotencyKey = strings.TrimSpace(op.IdempotencyKey)
	op.CreatedBy = strings.TrimSpace(op.CreatedBy)

	var missing []string
	if op.ID == "" {
		missing = append(missing, "id")
	}
	if op.RepoID == "" {
		missing = append(missing, "repo_id")
	}
	if op.CreatedBy == "" {
		missing = append(missing, "created_by")
	}
	if len(missing) > 0 {
		return core.Operation{}, fmt.Errorf("%w: required fields missing: %s", ErrInvalidOperation, strings.Join(missing, ", "))
	}
	if !op.Type.Valid() {
		return core.Operation{}, fmt.Errorf("%w: unsupported type %q", ErrInvalidOperation, op.Type)
	}
	if op.State == "" {
		op.State = core.OperationQueued
	}
	if op.State != core.OperationQueued {
		return core.Operation{}, fmt.Errorf("%w: create state must be %q, got %q", ErrInvalidOperation, core.OperationQueued, op.State)
	}
	return op, nil
}

func scanOperation(scanner repoScanner) (core.Operation, error) {
	var op core.Operation
	var idempotencyKey sql.NullString
	if err := scanner.Scan(
		&op.ID,
		&op.RepoID,
		&op.Type,
		&op.State,
		&idempotencyKey,
		&op.CreatedBy,
		&op.CreatedAt,
		&op.UpdatedAt,
	); err != nil {
		return core.Operation{}, err
	}
	if idempotencyKey.Valid {
		op.IdempotencyKey = idempotencyKey.String
	}
	return op, nil
}

// pgBranchWatchStore

type pgBranchWatchStore struct{ pool *pgxpool.Pool }

func (s *pgBranchWatchStore) UpsertBranchWatch(ctx context.Context, watch core.BranchWatch) (core.BranchWatch, error) {
	const q = `
		INSERT INTO branch_watches (id, provider, repo_id, branch, created_at)
		VALUES ($1, $2, $3, $4, $5)
		ON CONFLICT (provider, repo_id, branch) DO UPDATE
			SET id = branch_watches.id, created_at = branch_watches.created_at
		RETURNING id, provider, repo_id, branch, created_at
	`
	var out core.BranchWatch
	row := s.pool.QueryRow(ctx, q, watch.ID, watch.Provider, watch.RepoID, watch.Branch, watch.CreatedAt)
	if err := row.Scan(&out.ID, &out.Provider, &out.RepoID, &out.Branch, &out.CreatedAt); err != nil {
		return core.BranchWatch{}, fmt.Errorf("upsert branch watch: %w", err)
	}
	return out, nil
}

func (s *pgBranchWatchStore) FindBranchWatch(ctx context.Context, provider, repoID, branch string) (core.BranchWatch, bool, error) {
	const q = `SELECT id, provider, repo_id, branch, created_at FROM branch_watches WHERE provider=$1 AND repo_id=$2 AND branch=$3`
	var out core.BranchWatch
	row := s.pool.QueryRow(ctx, q, provider, repoID, branch)
	if err := row.Scan(&out.ID, &out.Provider, &out.RepoID, &out.Branch, &out.CreatedAt); err != nil {
		if isNoRows(err) {
			return core.BranchWatch{}, false, nil
		}
		return core.BranchWatch{}, false, fmt.Errorf("find branch watch: %w", err)
	}
	return out, true, nil
}

func (s *pgBranchWatchStore) ListBranchWatches(ctx context.Context) ([]core.BranchWatch, error) {
	const q = `SELECT id, provider, repo_id, branch, created_at FROM branch_watches ORDER BY id`
	rows, err := s.pool.Query(ctx, q)
	if err != nil {
		return nil, fmt.Errorf("list branch watches: %w", err)
	}
	defer rows.Close()
	var out []core.BranchWatch
	for rows.Next() {
		var w core.BranchWatch
		if err := rows.Scan(&w.ID, &w.Provider, &w.RepoID, &w.Branch, &w.CreatedAt); err != nil {
			return nil, fmt.Errorf("scan branch watch: %w", err)
		}
		out = append(out, w)
	}
	return out, rows.Err()
}

// pgRevisionCursorStore

type pgRevisionCursorStore struct{ pool *pgxpool.Pool }

func (s *pgRevisionCursorStore) UpsertRevisionCursor(ctx context.Context, cursor core.RevisionCursor) error {
	const q = `
		INSERT INTO revision_cursors (repo_id, branch, revision, observed_at)
		VALUES ($1, $2, $3, $4)
		ON CONFLICT (repo_id, branch) DO UPDATE
			SET revision = EXCLUDED.revision, observed_at = EXCLUDED.observed_at
	`
	_, err := s.pool.Exec(ctx, q, cursor.RepoID, cursor.Branch, cursor.Revision, cursor.ObservedAt)
	if err != nil {
		return fmt.Errorf("upsert revision cursor: %w", err)
	}
	return nil
}

func (s *pgRevisionCursorStore) GetRevisionCursor(ctx context.Context, repoID, branch string) (core.RevisionCursor, bool, error) {
	const q = `SELECT repo_id, branch, revision, observed_at FROM revision_cursors WHERE repo_id=$1 AND branch=$2`
	var out core.RevisionCursor
	row := s.pool.QueryRow(ctx, q, repoID, branch)
	if err := row.Scan(&out.RepoID, &out.Branch, &out.Revision, &out.ObservedAt); err != nil {
		if isNoRows(err) {
			return core.RevisionCursor{}, false, nil
		}
		return core.RevisionCursor{}, false, fmt.Errorf("get revision cursor: %w", err)
	}
	return out, true, nil
}

// pgProviderDeliveryStore

type pgProviderDeliveryStore struct{ pool *pgxpool.Pool }

func (s *pgProviderDeliveryStore) RecordOnce(ctx context.Context, delivery core.ProviderDelivery) (DeliveryResult, error) {
	const insert = `
		INSERT INTO provider_deliveries
			(id, provider, delivery_id, dedupe_key, event_id, repo_id, branch, revision, created_at)
		VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
		ON CONFLICT (provider, dedupe_key) DO NOTHING
	`
	tag, err := s.pool.Exec(ctx, insert,
		delivery.ID, delivery.Provider, delivery.DeliveryID, delivery.DedupeKey,
		delivery.EventID, delivery.RepoID, delivery.Branch, delivery.Revision,
		delivery.CreatedAt,
	)
	if err != nil {
		return DeliveryResult{}, fmt.Errorf("record delivery: %w", err)
	}
	if tag.RowsAffected() == 1 {
		return DeliveryResult{First: true}, nil
	}
	// Duplicate: fetch existing event_id and created_at for idempotent response.
	const sel = `SELECT event_id, created_at FROM provider_deliveries WHERE provider=$1 AND dedupe_key=$2`
	var existingEventID string
	var existingCreatedAt time.Time
	row := s.pool.QueryRow(ctx, sel, delivery.Provider, delivery.DedupeKey)
	if err := row.Scan(&existingEventID, &existingCreatedAt); err != nil {
		return DeliveryResult{}, fmt.Errorf("fetch existing delivery: %w", err)
	}
	return DeliveryResult{
		First:             false,
		ExistingEventID:   existingEventID,
		ExistingCreatedAt: existingCreatedAt,
	}, nil
}

func (s *pgProviderDeliveryStore) DeleteDelivery(ctx context.Context, provider, dedupeKey string) error {
	const query = `DELETE FROM provider_deliveries WHERE provider=$1 AND dedupe_key=$2`
	_, err := s.pool.Exec(ctx, query, provider, dedupeKey)
	if err != nil {
		return fmt.Errorf("delete delivery: %w", err)
	}
	return nil
}

func isNoRows(err error) bool {
	return err != nil && (errors.Is(err, pgx.ErrNoRows) || strings.Contains(err.Error(), "no rows"))
}

func isUniqueViolation(err error) bool {
	_, ok := uniqueViolationConstraint(err)
	return ok
}

// uniqueViolationConstraint reports whether err is a Postgres unique violation
// (SQLSTATE 23505) and returns the violated constraint/index name when so. The
// name lets callers distinguish, for example, an idempotency-key index conflict
// from a primary-key collision.
func uniqueViolationConstraint(err error) (string, bool) {
	var pgErr *pgconn.PgError
	if errors.As(err, &pgErr) && pgErr.Code == "23505" {
		return pgErr.ConstraintName, true
	}
	return "", false
}

// pgOperationEventStore

type pgOperationEventStore struct {
	pool *pgxpool.Pool
}

func (s *pgOperationEventStore) AppendEvent(ctx context.Context, ev OperationEvent) error {
	opID := strings.TrimSpace(ev.OperationID)
	eventID := strings.TrimSpace(ev.Event.ID)
	eventType := strings.TrimSpace(ev.Event.Type)
	subject := strings.TrimSpace(ev.Event.Subject)

	if eventID == "" || eventType == "" || subject == "" {
		return fmt.Errorf("%w: event_id, type, and subject are required", ErrInvalidOperation)
	}

	if ev.PublishedAt != nil {
		return fmt.Errorf("%w: published_at must be nil on append", ErrInvalidOperation)
	}

	payload, err := validateAndNormalizePayload(ev.Event.Payload)
	if err != nil {
		return err
	}

	createdAt := ev.Event.CreatedAt
	if createdAt.IsZero() {
		createdAt = time.Now().UTC()
	} else {
		createdAt = createdAt.UTC()
	}

	const q = `
		INSERT INTO operation_events (id, operation_id, type, subject, payload, created_at)
		VALUES ($1, $2, $3, $4, $5, $6)
	`
	var opIDVal *string
	if opID != "" {
		opIDVal = &opID
	}
	_, err = s.pool.Exec(ctx, q, eventID, opIDVal, eventType, subject, payload, createdAt)
	if err != nil {
		return fmt.Errorf("append operation event: %w", err)
	}
	return nil
}

func validateAndNormalizePayload(payload []byte) ([]byte, error) {
	if len(payload) == 0 {
		return []byte("{}"), nil
	}
	var m map[string]any
	if err := json.Unmarshal(payload, &m); err != nil {
		return nil, fmt.Errorf("%w: payload must be a valid JSON object", ErrInvalidOperation)
	}
	if m == nil {
		return nil, fmt.Errorf("%w: payload cannot be null", ErrInvalidOperation)
	}
	return payload, nil
}

func (s *pgOperationEventStore) ListEvents(ctx context.Context, operationID string) ([]OperationEvent, error) {
	operationID = strings.TrimSpace(operationID)
	if operationID == "" {
		return nil, fmt.Errorf("%w: operation_id is required", ErrInvalidOperation)
	}

	const q = `
		SELECT operation_id, id, type, subject, payload, created_at, published_at
		FROM operation_events
		WHERE operation_id=$1
		ORDER BY created_at, id
	`
	rows, err := s.pool.Query(ctx, q, operationID)
	if err != nil {
		return nil, fmt.Errorf("list operation events: %w", err)
	}
	defer rows.Close()

	var out []OperationEvent
	for rows.Next() {
		ev, err := scanOperationEvent(rows)
		if err != nil {
			return nil, fmt.Errorf("scan operation event: %w", err)
		}
		out = append(out, ev)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("list operation events rows error: %w", err)
	}
	return out, nil
}

func (s *pgOperationEventStore) ListPendingEvents(ctx context.Context, limit int) ([]OperationEvent, error) {
	if limit <= 0 {
		return nil, fmt.Errorf("%w: limit must be positive", ErrInvalidOperation)
	}

	const q = `
		SELECT operation_id, id, type, subject, payload, created_at, published_at
		FROM operation_events
		WHERE published_at IS NULL
		ORDER BY created_at, id
		LIMIT $1
	`
	rows, err := s.pool.Query(ctx, q, limit)
	if err != nil {
		return nil, fmt.Errorf("list pending operation events: %w", err)
	}
	defer rows.Close()

	var out []OperationEvent
	for rows.Next() {
		ev, err := scanOperationEvent(rows)
		if err != nil {
			return nil, fmt.Errorf("scan operation event: %w", err)
		}
		out = append(out, ev)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("list pending operation events rows error: %w", err)
	}
	return out, nil
}

func (s *pgOperationEventStore) MarkPublished(ctx context.Context, eventID string, now time.Time) (OperationEvent, error) {
	eventID = strings.TrimSpace(eventID)
	if eventID == "" {
		return OperationEvent{}, fmt.Errorf("%w: event_id is required", ErrInvalidOperation)
	}

	const q = `
		UPDATE operation_events
		SET published_at=$2
		WHERE id=$1
		RETURNING operation_id, id, type, subject, payload, created_at, published_at
	`
	ev, err := scanOperationEvent(s.pool.QueryRow(ctx, q, eventID, now.UTC()))
	if err != nil {
		if isNoRows(err) {
			return OperationEvent{}, fmt.Errorf("%w: event %s not found", ErrOperationNotFound, eventID)
		}
		return OperationEvent{}, fmt.Errorf("scan operation event: %w", err)
	}
	return ev, nil
}

func scanOperationEvent(scanner repoScanner) (OperationEvent, error) {
	var ev OperationEvent
	var opID sql.NullString
	var publishedAt sql.NullTime
	if err := scanner.Scan(
		&opID,
		&ev.Event.ID,
		&ev.Event.Type,
		&ev.Event.Subject,
		&ev.Event.Payload,
		&ev.Event.CreatedAt,
		&publishedAt,
	); err != nil {
		return OperationEvent{}, err
	}
	if opID.Valid {
		ev.OperationID = opID.String
	}
	ev.Event.CreatedAt = ev.Event.CreatedAt.UTC()
	if publishedAt.Valid {
		t := publishedAt.Time.UTC()
		ev.PublishedAt = &t
	}
	return ev, nil
}

// pgAgentRunInputStore

type pgAgentRunInputStore struct{ pool *pgxpool.Pool }

func (s *pgAgentRunInputStore) CreateAgentRunInput(ctx context.Context, input core.DurableAgentRunInput) error {
	input.OperationID = strings.TrimSpace(input.OperationID)
	input.RepoID = strings.TrimSpace(input.RepoID)
	input.Branch = strings.TrimSpace(input.Branch)
	input.WorkspacePath = strings.TrimSpace(input.WorkspacePath)
	input.Instruction = strings.TrimSpace(input.Instruction)
	input.ExpectedRevision = strings.TrimSpace(input.ExpectedRevision)

	var missing []string
	if input.OperationID == "" {
		missing = append(missing, "operation_id")
	}
	if input.RepoID == "" {
		missing = append(missing, "repo_id")
	}
	if input.Branch == "" {
		missing = append(missing, "branch")
	}
	if input.WorkspacePath == "" {
		missing = append(missing, "workspace_path")
	}
	if input.Instruction == "" {
		missing = append(missing, "instruction")
	}
	if input.ExpectedRevision == "" {
		missing = append(missing, "expected_revision")
	}
	if len(missing) > 0 {
		return fmt.Errorf("%w: required fields missing: %s", ErrInvalidAgentRunInput, strings.Join(missing, ", "))
	}

	policyJSON, err := json.Marshal(input.PolicyContext)
	if err != nil {
		return fmt.Errorf("%w: marshal policy_context: %v", ErrInvalidAgentRunInput, err)
	}

	createdAt := input.CreatedAt
	if createdAt.IsZero() {
		createdAt = time.Now().UTC()
	}

	const q = `
		INSERT INTO agent_run_inputs
			(operation_id, repo_id, branch, workspace_path, instruction, policy_context, expected_revision, created_at)
		VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
	`
	_, err = s.pool.Exec(ctx, q,
		input.OperationID, input.RepoID, input.Branch, input.WorkspacePath,
		input.Instruction, policyJSON, input.ExpectedRevision, createdAt,
	)
	if err != nil {
		return fmt.Errorf("create agent run input: %w", err)
	}
	return nil
}

func (s *pgAgentRunInputStore) GetAgentRunInput(ctx context.Context, operationID string) (core.DurableAgentRunInput, error) {
	operationID = strings.TrimSpace(operationID)
	if operationID == "" {
		return core.DurableAgentRunInput{}, fmt.Errorf("%w: operation_id is required", ErrAgentRunInputNotFound)
	}

	const q = `
		SELECT operation_id, repo_id, branch, workspace_path, instruction, policy_context, expected_revision, created_at
		FROM agent_run_inputs
		WHERE operation_id=$1
	`
	var out core.DurableAgentRunInput
	var policyJSON []byte
	row := s.pool.QueryRow(ctx, q, operationID)
	if err := row.Scan(
		&out.OperationID, &out.RepoID, &out.Branch, &out.WorkspacePath,
		&out.Instruction, &policyJSON, &out.ExpectedRevision, &out.CreatedAt,
	); err != nil {
		if isNoRows(err) {
			return core.DurableAgentRunInput{}, fmt.Errorf("%w: %s", ErrAgentRunInputNotFound, operationID)
		}
		return core.DurableAgentRunInput{}, fmt.Errorf("get agent run input: %w", err)
	}
	out.CreatedAt = out.CreatedAt.UTC()
	if len(policyJSON) > 0 {
		if err := json.Unmarshal(policyJSON, &out.PolicyContext); err != nil {
			return core.DurableAgentRunInput{}, fmt.Errorf("unmarshal policy_context: %w", err)
		}
	}
	return out, nil
}

// pgWebhookDeliveryStore

type pgWebhookDeliveryStore struct{ pool *pgxpool.Pool }

func (s *pgWebhookDeliveryStore) EnqueueDelivery(ctx context.Context, delivery core.WebhookDelivery) (WebhookDeliveryCreateResult, error) {
	if delivery.ID == "" {
		delivery.ID = newID()
	}
	if delivery.Status == "" {
		delivery.Status = core.WebhookDeliveryPending
	}

	now := time.Now().UTC()
	createdAt := delivery.CreatedAt
	if createdAt.IsZero() {
		createdAt = now
	}
	updatedAt := delivery.UpdatedAt
	if updatedAt.IsZero() {
		updatedAt = now
	}
	nextAttemptAt := delivery.NextAttemptAt
	if nextAttemptAt.IsZero() {
		nextAttemptAt = now
	}

	const insert = `
		INSERT INTO webhook_deliveries
			(id, event_id, subscription_id, status, attempt_count, next_attempt_at, last_status_code, last_error, created_at, updated_at)
		VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
		ON CONFLICT (event_id, subscription_id) DO NOTHING
	`
	tag, err := s.pool.Exec(ctx, insert,
		delivery.ID, delivery.EventID, delivery.SubscriptionID, string(delivery.Status),
		delivery.AttemptCount, nextAttemptAt, delivery.LastStatusCode, delivery.LastError,
		createdAt, updatedAt,
	)
	if err != nil {
		return WebhookDeliveryCreateResult{}, fmt.Errorf("enqueue webhook delivery: %w", err)
	}
	if tag.RowsAffected() == 1 {
		delivery.CreatedAt = createdAt
		delivery.UpdatedAt = updatedAt
		delivery.NextAttemptAt = nextAttemptAt
		return WebhookDeliveryCreateResult{Delivery: delivery, Created: true}, nil
	}

	const sel = `
		SELECT id, event_id, subscription_id, status, attempt_count, next_attempt_at, last_status_code, last_error, created_at, updated_at
		FROM webhook_deliveries
		WHERE event_id=$1 AND subscription_id=$2
	`
	var existing core.WebhookDelivery
	var statusStr string
	row := s.pool.QueryRow(ctx, sel, delivery.EventID, delivery.SubscriptionID)
	if err := row.Scan(
		&existing.ID, &existing.EventID, &existing.SubscriptionID, &statusStr,
		&existing.AttemptCount, &existing.NextAttemptAt, &existing.LastStatusCode, &existing.LastError,
		&existing.CreatedAt, &existing.UpdatedAt,
	); err != nil {
		return WebhookDeliveryCreateResult{}, fmt.Errorf("fetch existing webhook delivery: %w", err)
	}
	existing.Status = core.WebhookDeliveryStatus(statusStr)
	existing.NextAttemptAt = existing.NextAttemptAt.UTC()
	existing.CreatedAt = existing.CreatedAt.UTC()
	existing.UpdatedAt = existing.UpdatedAt.UTC()
	return WebhookDeliveryCreateResult{Delivery: existing, Created: false}, nil
}

func (s *pgWebhookDeliveryStore) GetDelivery(ctx context.Context, id string) (core.WebhookDelivery, error) {
	const sel = `
		SELECT id, event_id, subscription_id, status, attempt_count, next_attempt_at, last_status_code, last_error, created_at, updated_at
		FROM webhook_deliveries
		WHERE id=$1
	`
	var out core.WebhookDelivery
	var statusStr string
	row := s.pool.QueryRow(ctx, sel, id)
	if err := row.Scan(
		&out.ID, &out.EventID, &out.SubscriptionID, &statusStr,
		&out.AttemptCount, &out.NextAttemptAt, &out.LastStatusCode, &out.LastError,
		&out.CreatedAt, &out.UpdatedAt,
	); err != nil {
		if isNoRows(err) {
			return core.WebhookDelivery{}, fmt.Errorf("webhook delivery not found: %s", id)
		}
		return core.WebhookDelivery{}, fmt.Errorf("get webhook delivery: %w", err)
	}
	out.Status = core.WebhookDeliveryStatus(statusStr)
	out.NextAttemptAt = out.NextAttemptAt.UTC()
	out.CreatedAt = out.CreatedAt.UTC()
	out.UpdatedAt = out.UpdatedAt.UTC()
	return out, nil
}

func (s *pgWebhookDeliveryStore) PickPendingDeliveries(ctx context.Context, limit int, now time.Time) ([]core.WebhookDelivery, error) {
	const q = `
		WITH selected AS (
			SELECT id
			FROM webhook_deliveries
			WHERE status IN ('pending', 'retryable') AND next_attempt_at <= $1
			ORDER BY next_attempt_at ASC, id ASC
			LIMIT $2
			FOR UPDATE SKIP LOCKED
		)
		UPDATE webhook_deliveries
		SET status = 'sending', updated_at = $3
		FROM selected
		WHERE webhook_deliveries.id = selected.id
		RETURNING webhook_deliveries.id, event_id, subscription_id, status, attempt_count, next_attempt_at, last_status_code, last_error, created_at, updated_at
	`
	rows, err := s.pool.Query(ctx, q, now, limit, now)
	if err != nil {
		return nil, fmt.Errorf("pick pending deliveries: %w", err)
	}
	defer rows.Close()

	var list []core.WebhookDelivery
	for rows.Next() {
		var d core.WebhookDelivery
		var statusStr string
		if err := rows.Scan(
			&d.ID, &d.EventID, &d.SubscriptionID, &statusStr,
			&d.AttemptCount, &d.NextAttemptAt, &d.LastStatusCode, &d.LastError,
			&d.CreatedAt, &d.UpdatedAt,
		); err != nil {
			return nil, fmt.Errorf("scan webhook delivery: %w", err)
		}
		d.Status = core.WebhookDeliveryStatus(statusStr)
		d.NextAttemptAt = d.NextAttemptAt.UTC()
		d.CreatedAt = d.CreatedAt.UTC()
		d.UpdatedAt = d.UpdatedAt.UTC()
		list = append(list, d)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("rows error: %w", err)
	}
	return list, nil
}

// StartDelivery claims a single delivery by id when it is pending/retryable and
// due. It returns the claimed delivery, true when a transition happened, and
// false when the delivery is not yet due or is in a terminal state.
func (s *pgWebhookDeliveryStore) StartDelivery(ctx context.Context, id string, now time.Time) (core.WebhookDelivery, bool, error) {
	const q = `
		UPDATE webhook_deliveries
		SET status = 'sending', updated_at = $2
		WHERE id = $1
		  AND status IN ('pending', 'retryable')
		  AND next_attempt_at <= $2
		RETURNING id, event_id, subscription_id, status, attempt_count, next_attempt_at, last_status_code, last_error, created_at, updated_at
	`
	var d core.WebhookDelivery
	var statusStr string
	row := s.pool.QueryRow(ctx, q, id, now)
	if err := row.Scan(
		&d.ID, &d.EventID, &d.SubscriptionID, &statusStr,
		&d.AttemptCount, &d.NextAttemptAt, &d.LastStatusCode, &d.LastError,
		&d.CreatedAt, &d.UpdatedAt,
	); err != nil {
		if isNoRows(err) {
			return core.WebhookDelivery{}, false, nil
		}
		return core.WebhookDelivery{}, false, fmt.Errorf("start delivery: %w", err)
	}
	d.Status = core.WebhookDeliveryStatus(statusStr)
	d.NextAttemptAt = d.NextAttemptAt.UTC()
	d.CreatedAt = d.CreatedAt.UTC()
	d.UpdatedAt = d.UpdatedAt.UTC()
	return d, true, nil
}

func (s *pgWebhookDeliveryStore) RecordOutcome(ctx context.Context, id string, status core.WebhookDeliveryStatus, statusCode int, lastErr string, nextAttemptAt time.Time, now time.Time) (core.WebhookDelivery, error) {
	const q = `
		UPDATE webhook_deliveries
		SET status = $2,
		    attempt_count = attempt_count + 1,
		    next_attempt_at = $3,
		    last_status_code = $4,
		    last_error = $5,
		    updated_at = $6
		WHERE id = $1
		RETURNING id, event_id, subscription_id, status, attempt_count, next_attempt_at, last_status_code, last_error, created_at, updated_at
	`
	var d core.WebhookDelivery
	var statusStr string
	row := s.pool.QueryRow(ctx, q, id, string(status), nextAttemptAt, statusCode, lastErr, now)
	if err := row.Scan(
		&d.ID, &d.EventID, &d.SubscriptionID, &statusStr,
		&d.AttemptCount, &d.NextAttemptAt, &d.LastStatusCode, &d.LastError,
		&d.CreatedAt, &d.UpdatedAt,
	); err != nil {
		if isNoRows(err) {
			return core.WebhookDelivery{}, fmt.Errorf("webhook delivery not found for outcome: %s", id)
		}
		return core.WebhookDelivery{}, fmt.Errorf("record outcome: %w", err)
	}
	d.Status = core.WebhookDeliveryStatus(statusStr)
	d.NextAttemptAt = d.NextAttemptAt.UTC()
	d.CreatedAt = d.CreatedAt.UTC()
	d.UpdatedAt = d.UpdatedAt.UTC()
	return d, nil
}

func newID() string {
	b := make([]byte, 16)
	if _, err := rand.Read(b); err != nil {
		panic(err)
	}
	return hex.EncodeToString(b)
}

// pgProviderConfigStore

type pgProviderConfigStore struct{ pool *pgxpool.Pool }

func newPgProviderConfigStore(pool *pgxpool.Pool) *pgProviderConfigStore {
	return &pgProviderConfigStore{pool: pool}
}

func normalizeProviderConfig(cfg provider.Config) provider.Config {
	cfg.ID = provider.ProviderID(strings.TrimSpace(strings.ToLower(string(cfg.ID))))
	cfg.Endpoint = strings.TrimSpace(cfg.Endpoint)
	cfg.CredentialRef = strings.TrimSpace(cfg.CredentialRef)
	return cfg
}

func validateProviderConfig(cfg provider.Config) error {
	if cfg.ID == "" {
		return fmt.Errorf("%w: id is required", ErrInvalidProviderConfig)
	}
	if cfg.Endpoint == "" {
		return fmt.Errorf("%w: endpoint is required", ErrInvalidProviderConfig)
	}
	if cfg.Capabilities == 0 {
		return fmt.Errorf("%w: capabilities must be non-zero", ErrInvalidProviderConfig)
	}
	return nil
}

func scanProviderConfig(scanner repoScanner) (provider.Config, error) {
	var cfg provider.Config
	var credentialRef sql.NullString
	var capabilities int64
	if err := scanner.Scan(
		&cfg.ID,
		&cfg.Endpoint,
		&credentialRef,
		&capabilities,
		&cfg.CreatedAt,
		&cfg.UpdatedAt,
	); err != nil {
		return provider.Config{}, err
	}
	cfg.Capabilities = provider.Capability(capabilities)
	if credentialRef.Valid {
		cfg.CredentialRef = credentialRef.String
	}
	return cfg, nil
}

func (s *pgProviderConfigStore) SaveProviderConfig(ctx context.Context, cfg provider.Config) (provider.Config, error) {
	cfg = normalizeProviderConfig(cfg)
	if err := validateProviderConfig(cfg); err != nil {
		return provider.Config{}, err
	}

	const q = `
		INSERT INTO provider_configs (id, endpoint, credential_ref, capabilities, created_at, updated_at)
		VALUES ($1, $2, $3, $4, now(), now())
		ON CONFLICT (id) DO UPDATE
			SET endpoint = EXCLUDED.endpoint,
			    credential_ref = EXCLUDED.credential_ref,
			    capabilities = EXCLUDED.capabilities,
			    updated_at = now()
		RETURNING id, endpoint, credential_ref, capabilities, created_at, updated_at
	`
	out, err := scanProviderConfig(s.pool.QueryRow(ctx, q,
		cfg.ID,
		cfg.Endpoint,
		nullableString(cfg.CredentialRef),
		int64(cfg.Capabilities),
	))
	if err != nil {
		return provider.Config{}, fmt.Errorf("save provider config: %w", err)
	}
	return out, nil
}

func (s *pgProviderConfigStore) GetProviderConfig(ctx context.Context, id provider.ProviderID) (provider.Config, bool, error) {
	id = provider.ProviderID(strings.TrimSpace(strings.ToLower(string(id))))
	if id == "" {
		return provider.Config{}, false, fmt.Errorf("%w: id is required", ErrInvalidProviderConfig)
	}

	const q = `SELECT id, endpoint, credential_ref, capabilities, created_at, updated_at FROM provider_configs WHERE id=$1`
	cfg, err := scanProviderConfig(s.pool.QueryRow(ctx, q, id))
	if err != nil {
		if isNoRows(err) {
			return provider.Config{}, false, nil
		}
		return provider.Config{}, false, fmt.Errorf("get provider config: %w", err)
	}
	return cfg, true, nil
}

func (s *pgProviderConfigStore) ListProviderConfigs(ctx context.Context) ([]provider.Config, error) {
	const q = `SELECT id, endpoint, credential_ref, capabilities, created_at, updated_at FROM provider_configs ORDER BY id`
	rows, err := s.pool.Query(ctx, q)
	if err != nil {
		return nil, fmt.Errorf("list provider configs: %w", err)
	}
	defer rows.Close()

	var out []provider.Config
	for rows.Next() {
		cfg, err := scanProviderConfig(rows)
		if err != nil {
			return nil, fmt.Errorf("scan provider config: %w", err)
		}
		out = append(out, cfg)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("list provider configs rows error: %w", err)
	}
	return out, nil
}
