package wait

import (
	"context"
	"errors"
	"fmt"
	"time"

	batchv1 "k8s.io/api/batch/v1"
	corev1 "k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/util/wait"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

var errJobFailed = errors.New("job is failed")

func GetJobCondition(conds []batchv1.JobCondition, ct batchv1.JobConditionType) *batchv1.JobCondition {
	for _, cond := range conds {
		if cond.Type == ct {
			return &cond
		}
	}

	return nil
}

func WaitForJobComplete(
	ctx context.Context,
	c client.Client,
	job *batchv1.Job,
	timeout time.Duration,
) error {
	if err := wait.PollImmediate(poll, timeout, func() (bool, error) {
		key := client.ObjectKeyFromObject(job)
		if err := c.Get(ctx, key, job); err != nil {
			if apierrors.IsNotFound(err) {
				return false, nil
			}

			return false, fmt.Errorf("can't get network %s: %w", key, err)
		}

		completeCond := GetJobCondition(job.Status.Conditions, batchv1.JobComplete)
		if completeCond != nil && completeCond.Status == corev1.ConditionTrue {
			return true, nil
		}

		failCond := GetJobCondition(job.Status.Conditions, batchv1.JobFailed)
		if failCond != nil && failCond.Status == corev1.ConditionTrue {
			return false, fmt.Errorf("reason: %s, message: %s, err: %w", failCond.Reason, failCond.Message, errJobFailed)
		}

		return false, nil
	}); err != nil {
		if errors.Is(err, wait.ErrWaitTimeout) {
			return fmt.Errorf("wait for job %v complete timeout: %w", job, err)
		}

		return fmt.Errorf("can't wait for job %v complete, error : %w", job, err)
	}

	return nil
}
