package ent

import (
	"context"
	"fmt"

	"entgo.io/ent/dialect/sql"
)

// Transaction will rollback if `f` returned any error.
func (c *Client) Transaction(ctx context.Context, f func(tx *Tx) error, opts ...*sql.TxOptions) (err error) {
	var opt *sql.TxOptions
	if len(opts) > 0 {
		opt = opts[0]
	}

	tx, err := c.BeginTx(ctx, opt)
	if err != nil {
		return err
	}

	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("panic in transaction: %v", r)
		}
		_ = tx.Rollback()
	}()

	if err = f(tx); err != nil {
		return err
	}
	if err = tx.Commit(); err != nil {
		return err
	}
	return nil
}
