package social

import (
	"context"
	"database/sql"
	"errors"
	"fmt"

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

// uniqueViolation is the PostgreSQL SQLSTATE for a unique-constraint violation.
const uniqueViolation = "23505"

// Store is the Postgres-backed query surface for the friend graph, per-user
// blocks and per-game chat.
type Store struct {
	db *sql.DB
}

// NewStore constructs a Store wrapping db.
func NewStore(db *sql.DB) *Store {
	return &Store{db: db}
}

// isUniqueViolation reports whether err is a PostgreSQL unique-constraint
// violation, used to collapse a request/insert race into a friendly error.
func isUniqueViolation(err error) bool {
	var pgErr *pgconn.PgError
	return errors.As(err, &pgErr) && pgErr.Code == uniqueViolation
}

// withTx wraps fn in a transaction, committing on nil and rolling back on error.
func withTx(ctx context.Context, db *sql.DB, fn func(tx *sql.Tx) error) error {
	tx, err := db.BeginTx(ctx, nil)
	if err != nil {
		return fmt.Errorf("begin tx: %w", err)
	}
	if err := fn(tx); err != nil {
		_ = tx.Rollback()
		return err
	}
	if err := tx.Commit(); err != nil {
		return fmt.Errorf("commit tx: %w", err)
	}
	return nil
}
