package localapiready

import (
	"context"
	"errors"
	"time"
)

type Config struct {
	Timeout  time.Duration
	Interval time.Duration
	Sleep    func(time.Duration)
}

func Wait(ctx context.Context, probe func(context.Context) error, cfg Config) error {
	if cfg.Timeout <= 0 {
		cfg.Timeout = 20 * time.Second
	}
	if cfg.Interval <= 0 {
		cfg.Interval = 500 * time.Millisecond
	}
	if cfg.Sleep == nil {
		cfg.Sleep = time.Sleep
	}

	waitCtx, cancel := context.WithTimeout(ctx, cfg.Timeout)
	defer cancel()

	var lastErr error
	for {
		if err := waitCtx.Err(); err != nil {
			if lastErr != nil && !errors.Is(err, context.Canceled) {
				return lastErr
			}
			return err
		}
		if err := probe(waitCtx); err == nil {
			return nil
		} else {
			lastErr = err
		}

		select {
		case <-waitCtx.Done():
			if lastErr != nil && !errors.Is(waitCtx.Err(), context.Canceled) {
				return lastErr
			}
			return waitCtx.Err()
		default:
		}
		cfg.Sleep(cfg.Interval)
	}
}
