// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.

// common-errors.go
package kern

import (
	"fmt"
	"strings"
)

func ErrMissingParams(funcName string, missing []string) (err error) {
	return fmt.Errorf("%s(): missing params -- %s", funcName, strings.Join(missing, ", "))
}

func ErrTooFewParams(funcName string, minArgs, maxArgs, argCount int) (err error) {
	if maxArgs < 0 {
		err = fmt.Errorf("%s(): too few params -- expected %d or more, got %d", funcName, minArgs, argCount)
	} else {
		err = fmt.Errorf("%s(): too few params -- expected %d, got %d", funcName, minArgs, argCount)
	}
	return
}

func ErrTooManyParams(funcName string, maxArgs, argCount int) (err error) {
	err = fmt.Errorf("%s(): too many params -- expected %d, got %d", funcName, maxArgs, argCount)
	return
}

// --- General errors

func ErrCantConvert(funcName string, value any, kind string) error {
	return fmt.Errorf("%s(): can't convert %s to %s", funcName, TypeName(value), kind)
}

func ErrExpectedGot(funcName string, kind string, value any) error {
	return fmt.Errorf("%s(): expected %s, got %s (%#v)", funcName, kind, TypeName(value), value)
}

func ErrFuncDivisionByZero(funcName string) error {
	return fmt.Errorf("%s(): division by zero", funcName)
}

// func ErrDivisionByZero() error {
// 	return fmt.Errorf("division by zero")
// }

// --- Parameter errors

// func ErrMissingRequiredParameter(funcName, paramName string) error {
// 	return fmt.Errorf("%s(): missing required parameter %q", funcName, paramName)
// }

func ErrInvalidParameterValue(funcName, paramName string, paramValue any) error {
	return fmt.Errorf("%s(): invalid value %s (%#v) for parameter %q", funcName, TypeName(paramValue), paramValue, paramName)
}

func undefArticle(s string) (article string) {
	if len(s) > 0 && strings.Contains("aeiou", s[0:1]) {
		article = "an"
	} else {
		article = "a"
	}
	return
}

func prependUndefArticle(s string) (result string) {
	return undefArticle(s) + " " + s
}

func ErrWrongParamType(funcName, paramName, paramType string, paramValue any) error {
	var artWantType, artGotType string
	gotType := TypeName(paramValue)
	artGotType = prependUndefArticle(gotType)
	artWantType = prependUndefArticle(paramType)
	return fmt.Errorf("%s(): the %q parameter must be %s, got %s (%v)", funcName, paramName, artWantType, artGotType, paramValue)
}

func ErrUnknownParam(funcName, paramName string) error {
	return fmt.Errorf("%s(): unknown parameter %q", funcName, paramName)
}

func ErrUnknownVar(funcName, varName string) error {
	return fmt.Errorf("%s(): unknown variable %q", funcName, varName)
}

func ErrFuncInvalidArg(funcName, details string) error {
	return fmt.Errorf("%s(): invalid argument -- %s", funcName, details)
}

// --- Operator errors

func ErrLeftOperandMustBeVariable(leftTerm, opTerm Term) error {
	return leftTerm.Errorf("left operand of %q must be a variable", opTerm.Source())
}
