// Package errors provides typed application errors with structured codes
// and wrapping helpers used across the GoHoarder service.
package errors

import (
	"fmt"
)

// Error represents a structured error with code and details
type Error struct {
	Details interface{} `json:"details,omitempty"`
	Cause   error       `json:"-"`
	Code    string      `json:"code"`
	Message string      `json:"message"`
	Trace   []string    `json:"trace,omitempty"`
}

// Error implements the error interface
func (e *Error) Error() string {
	if e.Cause != nil {
		return fmt.Sprintf("%s: %s (caused by: %v)", e.Code, e.Message, e.Cause)
	}
	return fmt.Sprintf("%s: %s", e.Code, e.Message)
}

// Unwrap returns the cause for errors.Is/As support
func (e *Error) Unwrap() error {
	return e.Cause
}

// New creates a new error with the given code and message
func New(code, message string) *Error {
	return &Error{
		Code:    code,
		Message: message,
	}
}

// WithDetails adds details to the error
func (e *Error) WithDetails(details interface{}) *Error {
	e.Details = details
	return e
}

// WithCause adds an underlying cause to the error
func (e *Error) WithCause(cause error) *Error {
	e.Cause = cause
	return e
}

// Wrap wraps an existing error with a new code and message
func Wrap(err error, code, message string) *Error {
	return &Error{
		Code:    code,
		Message: message,
		Cause:   err,
	}
}

// NotFound creates a not found error
func NotFound(message string) *Error {
	return New(ErrCodeNotFound, message)
}

// QuotaExceeded creates a quota exceeded error
func QuotaExceeded(limit int64) *Error {
	return New(ErrCodeQuotaExceeded, "Storage quota exceeded").
		WithDetails(map[string]interface{}{
			"limit_bytes": limit,
		})
}
