package buntest

import (
	"context"
	"errors"
	"net"
	"net/url"
	"os"
	"time"

	"gitea.dwysokinski.me/twhelp/corev3/internal/bun/migrations"
	"github.com/cenkalti/backoff/v4"
	"github.com/ory/dockertest/v3"
	"github.com/stretchr/testify/require"
	"github.com/uptrace/bun"
	"github.com/uptrace/bun/extra/bundebug"
)

const migrationTimeout = 10 * time.Second

func runMigrations(tb TestingTB, db *bun.DB) {
	tb.Helper()

	migrator := migrations.NewMigrator(db)
	ctx, cancel := context.WithTimeout(context.Background(), migrationTimeout)
	defer cancel()

	require.NoError(tb, migrator.Init(ctx), "couldn't init migrator")

	_, err := migrator.Migrate(ctx)
	require.NoError(tb, err, "couldn't apply migrations")
}

func getHostPort(resource *dockertest.Resource, id string) (string, error) {
	dockerURL := os.Getenv("DOCKER_HOST")
	if dockerURL == "" {
		return resource.GetHostPort(id), nil
	}

	u, err := url.Parse(dockerURL)
	if err != nil {
		return "", err
	}

	return net.JoinHostPort(u.Hostname(), resource.GetPort(id)), nil
}

func retry(bo backoff.BackOff, op backoff.Operation) error {
	if err := backoff.Retry(op, bo); err != nil {
		if bo.NextBackOff() == backoff.Stop {
			return errors.New("reached retry deadline")
		}

		return err
	}

	return nil
}

func newBunDebugHook() *bundebug.QueryHook {
	return bundebug.NewQueryHook(bundebug.FromEnv("BUNDEBUG"))
}
