// internal/utils/error.go
package utils

import "fmt"

// AppError represents a custom application error
type AppError struct {
	Code    string
	Message string
	Err     error
}

func (e *AppError) Error() string {
	if e.Err != nil {
		return fmt.Sprintf("%s: %s (%v)", e.Code, e.Message, e.Err)
	}
	return fmt.Sprintf("%s: %s", e.Code, e.Message)
}

// NewAppError creates a new application error
func NewAppError(code, message string, err error) *AppError {
	return &AppError{
		Code:    code,
		Message: message,
		Err:     err,
	}
}

// Common error codes
const (
	ErrCodeValidation    = "VALIDATION_ERROR"
	ErrCodeNotFound      = "NOT_FOUND"
	ErrCodeUnauthorized  = "UNAUTHORIZED"
	ErrCodeForbidden     = "FORBIDDEN"
	ErrCodeInternal      = "INTERNAL_ERROR"
	ErrCodeDuplicate     = "DUPLICATE_ERROR"
	ErrCodeBadRequest    = "BAD_REQUEST"
)

// Error constructors
func ValidationError(message string) *AppError {
	return NewAppError(ErrCodeValidation, message, nil)
}

func NotFoundError(message string) *AppError {
	return NewAppError(ErrCodeNotFound, message, nil)
}

func UnauthorizedError(message string) *AppError {
	return NewAppError(ErrCodeUnauthorized, message, nil)
}

func ForbiddenError(message string) *AppError {
	return NewAppError(ErrCodeForbidden, message, nil)
}

func InternalError(message string, err error) *AppError {
	return NewAppError(ErrCodeInternal, message, err)
}

func DuplicateError(message string) *AppError {
	return NewAppError(ErrCodeDuplicate, message, nil)
}

func BadRequestError(message string) *AppError {
	return NewAppError(ErrCodeBadRequest, message, nil)
}