package errors

import (
	"errors"
	"fmt"
	"path"
	"runtime"
	"slices"
	"strings"
)

// wrap stdlib errors functions to make it easier to import this package as a replacement
var As = errors.As
var Is = errors.Is
var Join = errors.Join
var New = errors.New

var ErrCommandNoArgs = New("this command does not take any arguments")
var ErrUnsupportedPlatform = New("unsupported platform")

func WithStack(err error) error {
	stack := []string{}
	pcs := make([]uintptr, 32)
	runtime.Callers(2, pcs)
	frames := runtime.CallersFrames(pcs)
	for {
		frame, more := frames.Next()
		if !strings.HasPrefix(frame.Function, "runtime.") {
			stack = append(stack, fmt.Sprintf("%s(%s:%d)", frame.Function, path.Base(frame.File), frame.Line))
		}
		if !more {
			break
		}
	}
	slices.Reverse(stack)
	return fmt.Errorf("%w at %s", err, strings.Join(stack, "->"))
}

func WithMessage(err error, msg string) error {
	if err == nil {
		return nil
	}
	return fmt.Errorf("%s: %w", msg, err)
}

func WithMessagef(err error, format string, args ...any) error {
	if err == nil {
		return nil
	}
	return fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err)
}
