package dbsync

import (
	"errors"
	"fmt"
	"strings"
)

// RetryableError 上游 IO / remote 暂不可达，agent 可稍后重试（不换 UUID）。
type RetryableError struct {
	Msg string
}

func (e *RetryableError) Error() string {
	if e == nil {
		return "retryable error"
	}
	return e.Msg
}

func Retryable(msg string) error {
	return &RetryableError{Msg: msg}
}

func Retryablef(format string, args ...any) error {
	return &RetryableError{Msg: fmt.Sprintf(format, args...)}
}

func IsRetryable(err error) bool {
	var r *RetryableError
	return errors.As(err, &r)
}

func wrapOpenRemote(err error) error {
	if err == nil {
		return nil
	}
	msg := err.Error()
	lower := strings.ToLower(msg)
	if strings.Contains(lower, "open remote") ||
		strings.Contains(lower, "unable to open") ||
		strings.Contains(lower, "no such file") ||
		strings.Contains(lower, "locked") ||
		strings.Contains(lower, "busy") ||
		strings.Contains(lower, "connection refused") ||
		strings.Contains(lower, "timeout") ||
		strings.Contains(lower, "i/o") {
		return Retryablef("open remote: %v", err)
	}
	return Retryablef("open remote: %v", err)
}
